Skip to content

feat: replace unmaintained rollbar and gobrake with modern versions#15

Merged
ankurs merged 4 commits intomainfrom
chore/phase2-error-notification
Mar 24, 2026
Merged

feat: replace unmaintained rollbar and gobrake with modern versions#15
ankurs merged 4 commits intomainfrom
chore/phase2-error-notification

Conversation

@ankurs
Copy link
Member

@ankurs ankurs commented Mar 24, 2026

Summary

  • Replace stvp/rollbar (unmaintained) with rollbar/rollbar-go v1.4.8 (official, actively maintained)
  • Replace gopkg.in/airbrake/gobrake.v2 (3 major versions behind) with airbrake/gobrake/v5
  • Remove convToRollbar() — new rollbar SDK captures stacks internally via runtime.Callers
  • Transitive getsentry/raven-go dependency removed by go mod tidy

Public API is fully backward compatible — all exported function signatures unchanged.

Changes

Old New Notes
stvp/rollbar rollbar/rollbar-go v1.4.8 SetToken/SetEnvironment instead of direct var assignment
rollbar.ErrorWithStack + Field rollbar.ErrorWithStackSkipWithExtras + map[string]interface{} Auto stack capture, no manual Frame conversion
gobrake.NewNotifier(id, key) gobrake.NewNotifierWithOptions(&NotifierOptions{...}) Options struct pattern

Test plan

  • make build passes
  • make test passes (go test -race ./...)
  • make lint passes (golangci-lint 0 issues + govulncheck 0 vulnerabilities)
  • Verified all exported function signatures unchanged via go doc
  • Verified rollbar.ERR/rollbar.CRIT constants have same string values

Summary by CodeRabbit

  • Chores
    • Updated error-tracking libraries (Rollbar and Airbrake clients) and related transitive dependencies, including Prometheus client upgrades; internal notification handling updated to align with new library APIs.
  • Tests
    • Added unit tests covering initialization and notification paths for the error-reporting integrations to ensure stability and prevent panics.

- Replace stvp/rollbar with rollbar/rollbar-go v1.4.8
  - Use SetToken/SetEnvironment instead of direct variable assignment
  - Use ErrorWithStackSkipWithExtras (auto-captures stack) instead of
    manual stack conversion via ErrorWithStack + custom Frame types
  - Remove convToRollbar() — no longer needed
- Replace gopkg.in/airbrake/gobrake.v2 with airbrake/gobrake/v5
  - Use NewNotifierWithOptions instead of NewNotifier

Public API is fully backward compatible — no signature changes.
@coderabbitai
Copy link

coderabbitai bot commented Mar 24, 2026

Warning

Rate limit exceeded

@ankurs has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minutes and 25 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 543e2902-70ac-496d-896b-47b4acf79b4c

📥 Commits

Reviewing files that changed from the base of the PR and between 53b8547 and 210a0f9.

📒 Files selected for processing (2)
  • notifier/notifier.go
  • notifier/notifier_rollbar_airbrake_test.go
📝 Walkthrough

Walkthrough

Upgrades error-notification clients and related indirect deps: Rollbar and Airbrake libraries updated and notifier implementation adapted to their new APIs; new tests exercise initialization and notification paths. (46 words)

Changes

Cohort / File(s) Summary
Dependency updates
go.mod
Replaced Rollbar client (github.com/stvp/rollbargithub.com/rollbar/rollbar-go v1.4.8), replaced Airbrake (gopkg.in/airbrake/gobrake.v2github.com/airbrake/gobrake/v5 v5.6.2), and bumped several indirect deps (Prometheus clients, procfs, tdigest, clockwork, pkg/errors).
Notifier implementation
notifier/notifier.go
Updated Airbrake initialization to NewNotifierWithOptions(...); updated Rollbar initialization and environment setters to use rollbar.SetToken() / rollbar.SetEnvironment(); replaced stack/field conversion and now call rollbar.ErrorWithStackSkipWithExtras(...) with an extras map; removed convToRollbar.
Tests
notifier/notifier_rollbar_airbrake_test.go
Added tests for InitRollbar, InitAirbrake, Notify (no-panic when Rollbar disabled), NotifyOnPanic (no unhandled panic), and SetEnvironment with Airbrake; tests save/restore package-level state to avoid interference.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped through modules, bright and spry,
Swapped tokens, traces, gave old calls goodbye.
New notifiers snug in the code's neat lair,
Errors now travel with extra care.
Thump-thump — deploy, I nibble a carrot for flair! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: replacing unmaintained Rollbar and Gobrake libraries with modern, actively maintained versions. It accurately reflects the primary objective of the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/phase2-error-notification

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR modernizes the notifier integrations by replacing unmaintained/old Rollbar and Airbrake SDKs with their current maintained equivalents, while keeping the public notifier API stable.

Changes:

  • Replace stvp/rollbar with rollbar/rollbar-go and update initialization + notification calls to the new API.
  • Replace gopkg.in/airbrake/gobrake.v2 with github.com/airbrake/gobrake/v5 and update notifier initialization accordingly.
  • Remove the custom Rollbar stack conversion helper and rely on the new Rollbar SDK’s stack capture.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.

File Description
notifier/notifier.go Updates Rollbar/Airbrake SDK usage (init + notify paths) and removes Rollbar stack conversion helper.
go.mod Switches direct dependencies to rollbar/rollbar-go and airbrake/gobrake/v5; updates indirect requirements after tidy.
go.sum Reflects updated dependency graph from the Rollbar/Airbrake upgrades and go mod tidy.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Fix import ordering (goimports-compatible)
- Add tests for InitRollbar, InitAirbrake, SetEnvironment
- Avoid rollbar-go global client race by testing notify paths
  with rollbar disabled (rollbar-go has internal async transport race)
@ankurs
Copy link
Member Author

ankurs commented Mar 24, 2026

Addressing review comments in 53b8547:

  1. Import ordering: Fixed — gobrake import now sorts before getsentry (goimports-compatible).

  2. Rollbar/Airbrake test coverage: Added notifier_rollbar_airbrake_test.go with tests for InitRollbar, InitAirbrake, SetEnvironment, and notify paths. Note: rollbar-go's global async transport has an internal data race on SetToken (upstream issue), so notify-path tests run with rollbar disabled to avoid false -race failures.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
notifier/notifier.go (1)

111-114: Seed Airbrake's init-time environment from the stored package env.

gobrake/v5 exposes NotifierOptions.Environment, so wiring the already stored env into NewNotifierWithOptions would make SetEnvironment calls that happen before InitAirbrake take effect without requiring callers to reapply them. (pkg.go.dev)

♻️ Suggested follow-up
 func InitAirbrake(projectID int64, projectKey string) {
 	airbrake = gobrake.NewNotifierWithOptions(&gobrake.NotifierOptions{
 		ProjectId:  projectID,
 		ProjectKey: projectKey,
+		Environment: sentryEnvironment,
 	})
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@notifier/notifier.go` around lines 111 - 114, The Airbrake notifier is
created without seeding the environment, so SetEnvironment calls made before
InitAirbrake don't take effect; update the gobrake.NewNotifierWithOptions call
that constructs airbrake to populate NotifierOptions.Environment using the
stored env variable (the same env you currently persist and later set in
SetEnvironment), i.e. add Environment: <storedEnv> to the NotifierOptions passed
to NewNotifierWithOptions in InitAirbrake so early environment state is honored.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@notifier/notifier.go`:
- Around line 121-122: The Rollbar integration currently loses ErrorExt stack
frames; update InitRollbar() (or the Rollbar call sites that call
rollbar.ErrorWithStackSkipWithExtras) to convert ErrorExt's
StackFrame()/Callers() into Rollbar-compatible stack data and inject it into the
extras map (similar to convToGoBrake()), or alternatively implement a Stack()
[]runtime.Frame method on ErrorExt or call rollbar.SetStackTracer() with a
tracer that reads ErrorExt. Locate usages of ErrorWithStackSkipWithExtras and
ensure when err is an ErrorExt you extract err.StackFrame()/err.Callers(),
transform each frame into Rollbar's expected structure, and add them to the
extras argument so Rollbar receives the pre-captured frames.

---

Nitpick comments:
In `@notifier/notifier.go`:
- Around line 111-114: The Airbrake notifier is created without seeding the
environment, so SetEnvironment calls made before InitAirbrake don't take effect;
update the gobrake.NewNotifierWithOptions call that constructs airbrake to
populate NotifierOptions.Environment using the stored env variable (the same env
you currently persist and later set in SetEnvironment), i.e. add Environment:
<storedEnv> to the NotifierOptions passed to NewNotifierWithOptions in
InitAirbrake so early environment state is honored.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a71039da-b8fe-4191-b432-957782a49134

📥 Commits

Reviewing files that changed from the base of the PR and between ad176bc and 2271d9b.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (2)
  • go.mod
  • notifier/notifier.go

- Register rollbar.SetStackTracer() in InitRollbar() to convert
  ErrorExt.Callers() to []runtime.Frame — rollbar now uses pre-captured
  stacks instead of calling runtime.Callers() (matches Airbrake/Sentry)
- Seed Environment in InitAirbrake via NotifierOptions so
  SetEnvironment() calls before InitAirbrake() are honored
- Rename TestRollbarNotifyOnPanicDoesNotPanic to TestNotifyOnPanicRecoverable
- Add TestRollbarStackTracerExtractsErrorExtFrames
- Add TestInitAirbrakeSeededEnvironment
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
notifier/notifier.go (1)

120-123: ⚠️ Potential issue | 🟠 Major

Restore ErrorExt stack propagation for Rollbar.

The migration removed convToRollbar() but doesn’t replace it with rollbar.SetStackTracer(). rollbar-go only reuses embedded stacks from errors implementing its Stacker interface; otherwise its docs say it captures the stack where the error is reported. This package’s error API exposes Callers()/StackFrame() instead, so the Rollbar sends at Line 370 and Line 441 now fall back to notifier-site frames unless the concrete error types also implement Stack() []runtime.Frame. (raw.githubusercontent.com)

🔧 Suggested fix
 func InitRollbar(token, env string) {
 	rollbar.SetToken(token)
 	rollbar.SetEnvironment(env)
+	rollbar.SetStackTracer(func(err error) ([]runtime.Frame, bool) {
+		if e, ok := err.(errors.ErrorExt); ok {
+			callers := runtime.CallersFrames(e.Callers())
+			frames := make([]runtime.Frame, 0, len(e.Callers()))
+			for {
+				frame, more := callers.Next()
+				frames = append(frames, frame)
+				if !more {
+					break
+				}
+			}
+			return frames, true
+		}
+		return rollbar.DefaultStackTracer(err)
+	})
 	rollbarInited = true
 }

Run this to verify there still isn’t a Rollbar-compatible stack adapter elsewhere in the repo:

#!/bin/bash
set -euo pipefail

echo "== rollbar stack tracer registrations =="
rg -n --type=go 'rollbar\.SetStackTracer\('

echo
echo "== rollbar-go Stacker implementations =="
rg -nP --type=go 'func\s+\([^)]+\)\s+Stack\(\)\s+\[\]runtime\.Frame'

echo
echo "== Rollbar call sites using ErrorWithStackSkipWithExtras =="
rg -n --type=go 'ErrorWithStackSkipWithExtras\(' notifier/notifier.go
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@notifier/notifier.go` around lines 120 - 123, InitRollbar currently only sets
token/env and lost the Rollbar stack propagation; add a rollbar.SetStackTracer
registration inside InitRollbar that provides an adapter converting this
package's error type (e.g., ErrorExt or any type exposing
Callers()/StackFrame()) to a rollbar.Stacker so Rollbar reuses embedded stacks
instead of capturing the report-site stack; implement the adapter as a function
referenced from InitRollbar (via rollbar.SetStackTracer) that inspects the
error, extracts frames via Callers()/StackFrame() or ErrorExt methods, and
returns a rollbar.Stacker-compatible value so existing Rollbar calls (the ones
at the notifier's call sites) get the original error stack.
🧹 Nitpick comments (1)
notifier/notifier_rollbar_airbrake_test.go (1)

9-17: Assert the migrated Rollbar state, not just local flags / no-panics.

These tests still pass if Line 121 or Line 473 stops calling Rollbar’s setters, because they only inspect rollbarInited or “does not panic”. rollbar-go exposes Token() and Environment() accessors on the managed client, so these paths can be checked directly. (pkg.go.dev)

🧪 Suggested assertions
 import (
 	"testing"
 
 	"github.com/go-coldbrew/errors"
+	rollbar "github.com/rollbar/rollbar-go"
 )
 
 func TestInitRollbar(t *testing.T) {
 	rollbarInited = false
-	t.Cleanup(func() { rollbarInited = false })
+	oldToken, oldEnv := rollbar.Token(), rollbar.Environment()
+	t.Cleanup(func() {
+		rollbarInited = false
+		rollbar.SetToken(oldToken)
+		rollbar.SetEnvironment(oldEnv)
+	})
 
 	InitRollbar("test-token", "test")
 	if !rollbarInited {
 		t.Error("expected rollbarInited to be true after InitRollbar")
 	}
+	if got := rollbar.Token(); got != "test-token" {
+		t.Fatalf("expected rollbar token to be set, got %q", got)
+	}
+	if got := rollbar.Environment(); got != "test" {
+		t.Fatalf("expected rollbar environment to be set, got %q", got)
+	}
 }
 
 func TestSetEnvironmentWithAirbrake(t *testing.T) {
 	old := airbrake
-	t.Cleanup(func() { airbrake = old })
+	oldEnv := rollbar.Environment()
+	oldSentryEnv := sentryEnvironment
+	t.Cleanup(func() {
+		airbrake = old
+		rollbar.SetEnvironment(oldEnv)
+		sentryEnvironment = oldSentryEnv
+	})
 
 	InitAirbrake(12345, "test-key")
-	// Should not panic
 	SetEnvironment("production")
+	if got := rollbar.Environment(); got != "production" {
+		t.Fatalf("expected rollbar environment to be updated, got %q", got)
+	}
+	if sentryEnvironment != "production" {
+		t.Fatalf("expected sentryEnvironment to be updated, got %q", sentryEnvironment)
+	}
 }

Also applies to: 54-60

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@notifier/notifier_rollbar_airbrake_test.go` around lines 9 - 17, Replace the
brittle local-flag assertion in TestInitRollbar with assertions against the
rollbar-go managed client: after calling InitRollbar("test-token", "test") call
the rollbar package accessors (rollbar.Token() and rollbar.Environment()) and
assert they equal "test-token" and "test" respectively, and keep resetting
global state in t.Cleanup; apply the same change to the similar test at lines
54-60 so both validate the migrated Rollbar state rather than just rollbarInited
or lack of panic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@notifier/notifier.go`:
- Around line 120-123: InitRollbar currently only sets token/env and lost the
Rollbar stack propagation; add a rollbar.SetStackTracer registration inside
InitRollbar that provides an adapter converting this package's error type (e.g.,
ErrorExt or any type exposing Callers()/StackFrame()) to a rollbar.Stacker so
Rollbar reuses embedded stacks instead of capturing the report-site stack;
implement the adapter as a function referenced from InitRollbar (via
rollbar.SetStackTracer) that inspects the error, extracts frames via
Callers()/StackFrame() or ErrorExt methods, and returns a
rollbar.Stacker-compatible value so existing Rollbar calls (the ones at the
notifier's call sites) get the original error stack.

---

Nitpick comments:
In `@notifier/notifier_rollbar_airbrake_test.go`:
- Around line 9-17: Replace the brittle local-flag assertion in TestInitRollbar
with assertions against the rollbar-go managed client: after calling
InitRollbar("test-token", "test") call the rollbar package accessors
(rollbar.Token() and rollbar.Environment()) and assert they equal "test-token"
and "test" respectively, and keep resetting global state in t.Cleanup; apply the
same change to the similar test at lines 54-60 so both validate the migrated
Rollbar state rather than just rollbarInited or lack of panic.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 76bf0d1e-9bb7-4bf4-b5ce-59a0be6a2fab

📥 Commits

Reviewing files that changed from the base of the PR and between 2271d9b and 53b8547.

📒 Files selected for processing (2)
  • notifier/notifier.go
  • notifier/notifier_rollbar_airbrake_test.go

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Return (nil, false) when filtered frames slice is empty so rollbar
  falls back to its built-in runtime.Callers() capture
- Reset rollbar global state (token, environment) in test cleanup
  to prevent state leaking between tests
@ankurs ankurs merged commit 7655740 into main Mar 24, 2026
8 checks passed
@ankurs ankurs deleted the chore/phase2-error-notification branch March 24, 2026 13:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants