Skip to content

feat: add DebugLogInterceptor for per-request debug logging#38

Merged
ankurs merged 3 commits intomainfrom
feat/debug-log-interceptor
Apr 9, 2026
Merged

feat: add DebugLogInterceptor for per-request debug logging#38
ankurs merged 3 commits intomainfrom
feat/debug-log-interceptor

Conversation

@ankurs
Copy link
Copy Markdown
Member

@ankurs ankurs commented Apr 9, 2026

Summary

  • New DebugLogInterceptor enables per-request debug logging via:
    • Proto field: bool debug or bool enable_debug on request message (auto-detected via type assertion, same pattern as TraceIdInterceptor)
    • gRPC metadata/HTTP header: x-debug-log-level (configurable via SetDebugLogHeaderName)
  • Combined with trace ID propagation, allows targeted production debugging with zero blast radius
  • Inserted after TraceIdInterceptor in the default chain
  • Configurable: SetDisableDebugLogInterceptor(bool), SetDebugLogHeaderName(string)
  • Also adds goleak.VerifyTestMain for goroutine leak detection

Test plan

  • TestDebugLogInterceptor_ProtoFieldDebug — GetDebug() true triggers debug level
  • TestDebugLogInterceptor_ProtoFieldEnableDebug — GetEnableDebug() true triggers debug level
  • TestDebugLogInterceptor_NoField — plain request, no override
  • TestDebugLogInterceptor_DebugFalse — GetDebug() false, no override
  • TestDebugLogInterceptor_Metadata — header triggers debug level
  • TestDebugLogInterceptor_CustomHeaderName — custom header name works
  • TestDebugLogInterceptor_Disabled — disabled via config, no override
  • make test and make lint clean

Summary by CodeRabbit

  • New Features

    • Added configurable debug log level control via gRPC metadata headers (default: x-debug-log-level) or protocol buffer message fields.
  • Tests

    • Integrated goroutine leak detection into test suite to improve reliability.
  • Chores

    • Updated logging, error handling, and distributed tracing library dependencies.

New interceptor that enables per-request debug logging via:
- Proto field: bool debug or bool enable_debug on request message
- gRPC metadata/HTTP header: x-debug-log-level (configurable)

Combined with trace ID propagation, this allows targeted production
debugging with zero blast radius. Inserted after TraceIdInterceptor
in the default chain.

Also adds goleak.VerifyTestMain for goroutine leak detection.
Copilot AI review requested due to automatic review settings April 9, 2026 05:35
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 9, 2026

📝 Walkthrough

Walkthrough

Updated three go-coldbrew package dependencies to newer patch/minor versions and added go.uber.org/goleak for goroutine leak detection. Implemented a new DebugLogInterceptor that dynamically adjusts request log levels based on proto debug fields or gRPC metadata headers, with comprehensive test coverage.

Changes

Cohort / File(s) Summary
Dependency Management
go.mod
Bumped github.com/go-coldbrew/errors to v0.2.14, github.com/go-coldbrew/log to v0.3.2, github.com/go-coldbrew/tracing to v0.2.2, and added go.uber.org/goleak v1.3.0 as a direct dependency.
Goroutine Leak Detection
goleak_test.go
Added TestMain entry point that integrates go.uber.org/goleak to verify no goroutine leaks, with explicit ignores for persistent background goroutines from rollbar-go and hystrix-go.
Debug Log Interceptor Feature
interceptors.go
Implemented new DebugLogInterceptor() that overrides request log levels based on proto debug fields or gRPC metadata headers; added configuration APIs (SetDisableDebugLogInterceptor, SetDebugLogHeaderName, GetDebugLogHeaderName) and integrated interceptor into the default chain after TraceIdInterceptor.
Interceptor Test Coverage
interceptors_test.go
Added 169 lines of test coverage for DebugLogInterceptor including proto-based debug flags, metadata header propagation, custom header names, disabled state, and test infrastructure reset logic.

Sequence Diagram

sequenceDiagram
    participant Client
    participant gRPCServer as gRPC Server
    participant DebugLogInterceptor
    participant ProtoMsg as Proto Message
    participant MetadataHeader as Metadata Header
    participant Logger

    Client->>gRPCServer: gRPC Request (with metadata)
    gRPCServer->>DebugLogInterceptor: Intercept Request
    DebugLogInterceptor->>ProtoMsg: Check GetDebug()/GetEnableDebug()
    alt Proto Has Debug Flag
        ProtoMsg-->>DebugLogInterceptor: Debug bool value
        DebugLogInterceptor->>Logger: Override log level based on proto
    else Proto Lacks Debug Flag
        ProtoMsg-->>DebugLogInterceptor: Field not found
        DebugLogInterceptor->>MetadataHeader: Check x-debug-log-level header
        MetadataHeader-->>DebugLogInterceptor: Header value (if present)
        DebugLogInterceptor->>Logger: Parse header and override log level
    end
    DebugLogInterceptor-->>gRPCServer: Continue with handler
    gRPCServer-->>Client: Response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 Hopping through the debug logs with glee,
A new interceptor now sets the decree—
Proto flags or headers parse the way,
Log levels adjust by the light of day!
Goleak hops in to catch loose threads—
No goroutines left to rest in their beds! 🎯

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.18% 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 'feat: add DebugLogInterceptor for per-request debug logging' accurately and clearly describes the main feature addition in the PR, matching the core functionality changes across all files.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/debug-log-interceptor

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

Adds a new unary server interceptor that can elevate per-request logging verbosity (intended for targeted production debugging) and wires it into the default interceptor chain, along with tests and goroutine-leak detection.

Changes:

  • Introduces DebugLogInterceptor with opt-in via request proto fields (GetDebug() / GetEnableDebug()) or gRPC metadata header (configurable name).
  • Updates DefaultInterceptors() to include DebugLogInterceptor (configurable disable switch).
  • Adds goleak.VerifyTestMain plus new unit tests covering the debug-log behavior and configuration.

Reviewed changes

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

File Description
interceptors.go Adds debug-log interceptor, config setters/getter, and inserts it into the default interceptor chain.
interceptors_test.go Adds unit tests for proto-field and metadata-triggered log-level overrides plus config behaviors.
goleak_test.go Adds package TestMain to run goleak and ignore known unavoidable goroutines.
go.mod Adds go.uber.org/goleak dependency for test leak detection.

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

Comment thread interceptors.go Outdated
Comment thread interceptors.go Outdated
Address review: trim and reject empty header names in SetDebugLogHeaderName.
Clarify that proto fields always set DebugLevel while the metadata header
accepts any valid log level.
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 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.

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

@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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
interceptors.go (1)

431-438: ⚠️ Potential issue | 🟠 Major

Move DebugLogInterceptor before the response-time logger.

Line 433 keeps ResponseTimeLoggingInterceptor outside the new interceptor, and its deferred log closes over the original ctx. That means requests with debug=true or x-debug-log-level still emit the default response-time log at the normal level, so the feature only affects downstream handlers/interceptors.

Proposed fix
 		ints = append(ints,
 			DefaultTimeoutInterceptor(),
-			ResponseTimeLoggingInterceptor(defaultFilterFunc),
 			TraceIdInterceptor(),
 		)
 		if !disableDebugLogInterceptor {
 			ints = append(ints, DebugLogInterceptor())
 		}
+		ints = append(ints,
+			ResponseTimeLoggingInterceptor(defaultFilterFunc),
+		)
 		if !disableProtoValidate {
 			ints = append(ints, ProtoValidateInterceptor())
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@interceptors.go` around lines 431 - 438, The ResponseTimeLoggingInterceptor
is appended before DebugLogInterceptor so its deferred log closes over the
original ctx and ignores debug log level changes; when
disableDebugLogInterceptor is false, move DebugLogInterceptor() into the ints
slice before ResponseTimeLoggingInterceptor(defaultFilterFunc) (i.e., ensure
ints is appended with DebugLogInterceptor() prior to
ResponseTimeLoggingInterceptor(defaultFilterFunc)) so the debug interceptor
wraps and influences the response-time logger; update the append order around
DefaultTimeoutInterceptor(), TraceIdInterceptor(),
ResponseTimeLoggingInterceptor(...), and DebugLogInterceptor() accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@interceptors.go`:
- Around line 431-438: The ResponseTimeLoggingInterceptor is appended before
DebugLogInterceptor so its deferred log closes over the original ctx and ignores
debug log level changes; when disableDebugLogInterceptor is false, move
DebugLogInterceptor() into the ints slice before
ResponseTimeLoggingInterceptor(defaultFilterFunc) (i.e., ensure ints is appended
with DebugLogInterceptor() prior to
ResponseTimeLoggingInterceptor(defaultFilterFunc)) so the debug interceptor
wraps and influences the response-time logger; update the append order around
DefaultTimeoutInterceptor(), TraceIdInterceptor(),
ResponseTimeLoggingInterceptor(...), and DebugLogInterceptor() accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0ca7fb61-444a-4c8e-acc4-31c1ded87889

📥 Commits

Reviewing files that changed from the base of the PR and between 96d0dda and 7b54614.

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

@ankurs ankurs merged commit 93d68bc into main Apr 9, 2026
7 checks passed
@ankurs ankurs deleted the feat/debug-log-interceptor branch April 9, 2026 07:28
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