Skip to content

feat: improve interceptor observability, performance, and stability#19

Merged
ankurs merged 7 commits intomainfrom
feat/improvements
Mar 22, 2026
Merged

feat: improve interceptor observability, performance, and stability#19
ankurs merged 7 commits intomainfrom
feat/improvements

Conversation

@ankurs
Copy link
Copy Markdown
Member

@ankurs ankurs commented Mar 22, 2026

Summary

  • Fix TraceIdInterceptor: was discarding the context returned by notifier.UpdateTraceId, causing trace IDs to not propagate to log fields in downstream handlers
  • Bounded notifications: Replace fire-and-forget go func() { notifier.Notify(...) }() with notifier.NotifyAsync() (bounded semaphore) to prevent goroutine explosion at scale
  • Richer error context: Add grpcMethod and duration tags to error notifications for better debugging in Sentry/Rollbar
  • Panic stack traces: Include debug.Stack() in PanicRecoveryInterceptor log and notification
  • gRPC status in logs: Add grpcCode field to response time log when error is non-nil
  • Configurable log level: SetResponseTimeLogLevel() (default Info) for services wanting to reduce log volume
  • Reduce allocations: Hoist strings.ToLower before loop in FilterMethodsFunc — 1 alloc/RPC instead of 3

Dependencies

  • Requires go-coldbrew/errors with NotifyAsync (this PR)

Test plan

  • Existing tests pass (make test -race)
  • Lint clean (golangci-lint run)
  • After errors is published, update go.mod to reference new version

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added SetResponseTimeLogLevel() to configure response time logging verbosity.
  • Improvements

    • Enhanced error reporting with gRPC error codes in logs.
    • Improved panic recovery with stack trace capture and reporting.
    • Optimized method filter matching performance.
  • Documentation

    • Clarified initialization ordering requirements and thread-safety constraints for interceptor configuration functions.

ankurs added 2 commits March 22, 2026 19:37
- Fix TraceIdInterceptor dropping updated context (trace IDs were
  partially lost for downstream handlers).
- Use NotifyAsync for bounded error notifications instead of
  unbounded fire-and-forget goroutines.
- Add grpcMethod and duration tags to error notifications.
- Add debug.Stack() to PanicRecoveryInterceptor for full panic traces.
- Add gRPC status code to response time log when error is non-nil.
- Add SetResponseTimeLogLevel for configurable log level (default Info).
- Reduce FilterMethodsFunc allocations by hoisting ToLower before loop.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 22, 2026

Warning

Rate limit exceeded

@ankurs has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 2 minutes and 50 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: 5d33c5c8-607b-4801-bfe5-6c775897bb78

📥 Commits

Reviewing files that changed from the base of the PR and between 7e6e90f and f9ee669.

📒 Files selected for processing (1)
  • interceptors.go
📝 Walkthrough

Walkthrough

Updated documentation generation tooling in the Makefile, enhanced package documentation for interceptors with initialization and concurrency requirements, added new SetResponseTimeLogLevel configuration function, updated dependencies, and refactored interceptor logic for improved error notification, logging level control, and stack trace capture.

Changes

Cohort / File(s) Summary
Build & Documentation Metadata
Makefile, documentations.go
Pinned gomarkdoc to @latest with explicit output path configuration; removed package documentation comment from documentations.go.
Package Documentation
README.md
Enhanced interceptor descriptions with initialization ordering requirements and concurrency constraints; documented new SetResponseTimeLogLevel(ctx context.Context, level loggers.Level) public API; updated function link anchors.
Dependencies
go.mod
Bumped github.com/go-coldbrew/errors to v0.2.2 and github.com/go-coldbrew/log to v0.2.6; added indirect dependencies github.com/nxadm/tail v1.4.11 and github.com/smartystreets/goconvey v1.8.1.
Interceptor Logic
interceptors.go
Added SetResponseTimeLogLevel() configuration and package-level responseTimeLogLevel variable; refactored response-time logging to use configurable log levels; converted ServerErrorInterceptor(s) from goroutine-based to direct async notifier invocations with duration tracking; enhanced PanicRecoveryInterceptor with stack trace capture; optimized FilterMethodsFunc lowercase conversion; corrected context reassignment in TraceIdInterceptor.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 With whiskers twitched and nose held high,
We log our errors, watch them fly!
New levels set, new traces caught,
These careful changes—cleanly wrought.
Async notifiers, stack so bright,
The interceptors dance just right! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title concisely summarizes the main changes: improvements to observability (grpcCode, configurable log levels, stack traces), performance (allocation reduction), and stability (replacing goroutines with bounded NotifyAsync). It aligns directly with the file changes and PR objectives.
Docstring Coverage ✅ Passed Docstring coverage is 87.50% which is sufficient. The required threshold is 80.00%.

✏️ 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 feat/improvements

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
Copy Markdown
Contributor

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 improves gRPC interceptor observability and stability by fixing trace ID propagation, enriching error/latency logging/notifications, and adding guardrails to prevent unbounded notifier goroutine creation.

Changes:

  • Fix TraceIdInterceptor to propagate the updated context returned by notifier.UpdateTraceId.
  • Replace fire-and-forget notifier goroutines with notifier.NotifyAsync and add richer tags (grpcMethod, duration); include panic stack traces in logs/notifications.
  • Enhance response time logging with grpcCode on errors and add a configurable response-time log level; reduce per-RPC allocations in FilterMethodsFunc.

Reviewed changes

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

File Description
README.md Updates generated docs and clarifies interceptor configuration constraints, but appears out of sync with the new exported API.
interceptors.go Implements the interceptor behavior changes: trace propagation fix, async/bounded notifications, richer logging/notification context, and new response-time log-level configuration.

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

Comment thread interceptors.go
Comment thread README.md Outdated
Comment thread README.md
Comment thread interceptors.go Outdated
Comment thread interceptors.go
Update dependencies to pick up NotifyAsync, bounded notifications,
and log.AddToContext. Fix Makefile doc target to use @latest and
output to README.md.
@ankurs
Copy link
Copy Markdown
Member Author

ankurs commented Mar 22, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 22, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

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 4 out of 5 changed files in this pull request and generated 4 comments.


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

Comment thread README.md Outdated
Comment thread Makefile
Comment thread interceptors.go Outdated
Comment thread interceptors.go
Comment on lines +46 to +53
responseTimeLogLevel loggers.Level = loggers.InfoLevel
)

// SetResponseTimeLogLevel sets the log level for response time logging.
// Default is InfoLevel. Must be called during initialization, before the server starts.
func SetResponseTimeLogLevel(level loggers.Level) {
responseTimeLogLevel = level
}
Copy link

Copilot AI Mar 22, 2026

Choose a reason for hiding this comment

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

SetResponseTimeLogLevel only affects the unary ResponseTimeLoggingInterceptor path; ResponseTimeLoggingStreamInterceptor still logs at Info unconditionally. If the goal is configurable log volume, consider applying responseTimeLogLevel (and optionally grpcCode) consistently to the stream response-time interceptor too.

Copilot uses AI. Check for mistakes.
- Add ctx context.Context param to SetResponseTimeLogLevel for API
  consistency with other config functions
- Add "Not safe for concurrent use" to docstring
- Apply responseTimeLogLevel and grpcCode to stream interceptor too
- Remove duplicate package doc from documentations.go, regenerate README
Copy link
Copy Markdown
Contributor

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 5 out of 6 changed files in this pull request and generated 2 comments.


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

Comment thread interceptors.go
Comment thread interceptors.go
…tream errors

- Move AddToLogContext("grpcMethod") before defer so the response time
  log captures the method field from the context
- Add duration tag to ServerErrorStreamInterceptor for consistent
  observability between unary and stream error notifications
Copy link
Copy Markdown
Contributor

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 5 out of 6 changed files in this pull request and generated 3 comments.


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

Comment thread interceptors.go
Comment thread interceptors.go
Comment thread interceptors.go
Copy link
Copy Markdown
Contributor

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 5 out of 6 changed files in this pull request and generated 2 comments.


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

Comment thread interceptors.go Outdated
Comment thread interceptors.go
@ankurs ankurs merged commit 1bae11a into main Mar 22, 2026
8 checks passed
@ankurs ankurs deleted the feat/improvements branch March 22, 2026 15:34
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