Skip to content

🔥 feat: Add support for contextual logs#4241

Draft
ReneWerner87 wants to merge 12 commits intomainfrom
codex/reusable-log-template
Draft

🔥 feat: Add support for contextual logs#4241
ReneWerner87 wants to merge 12 commits intomainfrom
codex/reusable-log-template

Conversation

@ReneWerner87
Copy link
Copy Markdown
Member

@ReneWerner87 ReneWerner87 commented Apr 27, 2026

Replaces the approach from #4106 and fixes #3763.

This keeps the original goal of making log.WithContext(...) useful for request-scoped application logs, but changes the design from automatic middleware extractors to an explicit, user-controlled template system similar to middleware/logger.

  • Extract logger template parsing/rendering into a shared internal logtemplate package.
  • Reuse the shared template engine in middleware/logger without duplicating template parsing logic.
  • Keep logger.Data.TemplateChain and logger.Data.LogFuncChain compatible for existing custom logger integrations.
  • Add log.SetContextTemplate so Fiber’s default logger can render contextual fields for log.WithContext.
  • Keep WithContext(ctx any) compatible with Fiber-supported context inputs such as fiber.Ctx, *fasthttp.RequestCtx-style UserValue contexts, and context.Context.
  • Add built-in ${value:key} support for ordinary context-style values.
  • Document contextual application logging with request middleware values, including request ID examples.
  • Add regression coverage for legacy logger chains, contextual tags, and ${value:key} rendering.

Validation

  • make lint
  • make test

Copilot AI review requested due to automatic review settings April 27, 2026 12:38
@ReneWerner87 ReneWerner87 requested a review from a team as a code owner April 27, 2026 12:38
@ReneWerner87 ReneWerner87 linked an issue Apr 27, 2026 that may be closed by this pull request
3 tasks
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a generic log-template engine and context-backed logging: compiles and executes ${tag[:param]} templates, exposes SetContextTemplate/MustSetContextTemplate and tag registration, updates logger and middleware to render context tags (e.g., request IDs), broadens WithContext to accept any, and updates docs/tests.

Changes

Cohort / File(s) Summary
Template engine
internal/logtemplate/template.go, internal/logtemplate/errors.go, internal/logtemplate/template_test.go
New generic template builder/executor, Buffer and generic Func types, Build/ExecuteChains, sentinel ErrParameterMissing, and unit tests for rendering and missing-parameter errors.
Context template API
log/context.go, log/context_test.go
New ContextConfig, ContextData, ContextTagFunc, SetContextTemplate/MustSetContextTemplate, RegisterContextTag helpers, default ${value:...} resolver, and comprehensive tests.
Logger core
log/default.go, log/default_test.go, log/log.go, log/fiberlog.go
WithContext now accepts any; default logger stores retained context-like value and injects rendered context-template output into log entries; tests updated.
Middleware logger
middleware/logger/logger.go, middleware/logger/default_logger.go, middleware/logger/config.go, middleware/logger/errors.go, middleware/logger/logger_test.go, middleware/logger/data.go
Switched to logtemplate.Build/ExecuteChains, replaced local Buffer/LogFunc with type aliases, introduced typed missing-parameter error mapping, precompiled read-only chains stored per-middleware, and updated tests.
Removed helper
middleware/logger/template_chain.go
Removed legacy buildLogFuncChain; its parsing logic moved into logtemplate.
Global tag registry & tags
middleware/logger/tags.go, middleware/logger/tags.go (usage across middleware)
Added thread-safe global tag registry (RegisterTag/MustRegisterTag) and merged global tags into per-middleware tag maps with per-instance CustomTags override semantics.
Middleware tag registrations
middleware/requestid/requestid.go, middleware/basicauth/basicauth.go, middleware/csrf/csrf.go, middleware/keyauth/keyauth.go, middleware/session/middleware.go
Added one-time registration of context/log tags (e.g., requestid, username, csrf-token, api-key, session-id) using sync.Once and tag registration helpers; tags emit redacted/derived values or nothing when absent.
Docs & generated interfaces
docs/api/log.md, docs/middleware/logger.md, docs/whats_new.md, ctx_interface_gen.go, req_interface_gen.go, res_interface_gen.go
Expanded docs and examples for context-aware logging, tag registration and formats; adjusted generated interface comments for FormFile/FormValue, AutoFormat, and getLocationFromRoute; updated AllLogger docs to reflect WithContext change.
Misc & tests
log/context.go (new), middleware/logger/*_test.go, middleware/logger/errors_test.go
Added/updated tests covering template rendering, error cases, registry behavior, partial-failure handling, and compatibility.

Sequence Diagram(s)

sequenceDiagram
    participant Handler as Route Handler
    participant Logger as Logger Instance
    participant Template as logtemplate.Template
    participant Buffer as Output Buffer
    participant Context as ctx (any)

    Handler->>Logger: WithContext(ctx)
    activate Logger
    Logger->>Logger: store retained context
    Logger-->>Handler: bound logger
    deactivate Logger

    Handler->>Logger: Info("message")
    activate Logger
    Logger->>Template: load precompiled template (if set)
    alt template present
        Template->>Template: ExecuteChains(Buffer, Context, ContextData)
        Template->>Context: resolve tags (e.g., request id)
        Context-->>Template: values
        Template->>Buffer: write rendered bytes
    end
    Logger->>Buffer: write log prefix + context output + message
    deactivate Logger
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Possibly related PRs

Suggested labels

codex

Suggested reviewers

  • gaby
  • sixcolors
  • efectn

Poem

🐰 I hopped through templates, nibbling tags in tune,
I carried tiny request ids beneath the moon.
Context snug in pockets, tags gleamed bright and new,
I stitched logs to routes — the tests gave a woo-hoo!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.83% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The PR title is vague and does not accurately reflect the main objectives. While it says 'Add support for contextual logs', the actual changes involve a comprehensive refactoring of template parsing/rendering shared across multiple logging systems, global tag registration, and integration across multiple middleware. Revise the title to better reflect the main changes, such as 'Extract log template engine for reusable context formatting' or 'Refactor: unify logger template rendering and add configurable context formats'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The PR description is comprehensive and addresses most required sections. It clearly states the problem, lists specific changes introduced, includes validation steps, and links to related issues. All key subsections of the template are covered.
Linked Issues check ✅ Passed The PR successfully addresses issue #3763 by implementing a template-based system that enables log.WithContext to carry request-scoped contextual fields like RequestID through explicit configuration via log.SetContextTemplate with built-in ${value:key} support.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the PR objectives: extracting logtemplate package, reusing it in middleware/logger, adding log context configuration APIs, and registering middleware-specific tags (requestid, basicauth, csrf, keyauth, session). No unrelated changes detected.

✏️ 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 codex/reusable-log-template

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


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

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a unified log template mechanism in the internal/logtemplate package, which is now utilized by both the log package and the logger middleware. Key enhancements include the addition of log.WithContext and log.SetContextTemplate to allow for consistent, context-aware logging across the application. Documentation and generated interface files were also updated to reflect these changes and clarify behavior regarding multipart form parsing and route URL generation. A review comment suggested optimizing slice allocation in the template builder to prevent unnecessary reallocations.

Comment thread internal/logtemplate/template.go Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 27, 2026

Codecov Report

❌ Patch coverage is 69.00000% with 62 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.93%. Comparing base (2b45a43) to head (d509f58).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
middleware/keyauth/keyauth.go 11.11% 14 Missing and 2 partials ⚠️
middleware/session/middleware.go 11.11% 14 Missing and 2 partials ⚠️
log/context.go 87.50% 8 Missing and 3 partials ⚠️
middleware/csrf/csrf.go 20.00% 6 Missing and 2 partials ⚠️
middleware/basicauth/basicauth.go 25.00% 4 Missing and 2 partials ⚠️
middleware/logger/tags.go 76.92% 3 Missing ⚠️
log/default.go 90.47% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4241      +/-   ##
==========================================
- Coverage   91.23%   90.93%   -0.31%     
==========================================
  Files         126      127       +1     
  Lines       12341    12493     +152     
==========================================
+ Hits        11259    11360     +101     
- Misses        678      722      +44     
- Partials      404      411       +7     
Flag Coverage Δ
unittests 90.93% <69.00%> (-0.31%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ReneWerner87 ReneWerner87 marked this pull request as draft April 27, 2026 12:40
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 introduces a shared internal log template engine to reuse template parsing/rendering across Fiber’s request logger middleware and the log.WithContext application logger, enabling consistent “contextual tag” rendering (e.g., request IDs).

Changes:

  • Extract template parsing/execution into internal/logtemplate and switch middleware/logger to use it.
  • Add configurable contextual template rendering for Fiber’s default logger via log.SetContextTemplate + log.WithContext.
  • Update docs and add tests for legacy logger chains, contextual tags, and ${value:key} rendering.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
internal/logtemplate/template.go Adds reusable template parsing + chain execution utilities.
internal/logtemplate/errors.go Introduces shared template parse error(s).
internal/logtemplate/template_test.go Adds unit tests for template execution and missing-parameter behavior.
middleware/logger/logger.go Replaces per-middleware template compilation with logtemplate.Build(...).
middleware/logger/default_logger.go Reuses shared chain executor for default logger rendering.
middleware/logger/config.go Re-exports shared Buffer/Func types for logger tag functions.
middleware/logger/errors.go Maps legacy logger template error to shared logtemplate error.
middleware/logger/template_chain.go Removes now-superseded in-package template compilation logic.
middleware/logger/logger_test.go Adds regression coverage for legacy TemplateChain/LogFuncChain behavior.
log/context.go Adds SetContextTemplate and ${value:key} tag support for default logger context enrichment.
log/default.go Implements contextual template rendering in default logger when bound via WithContext.
log/context_test.go Adds tests for ${value:key} and custom context tags.
log/default_test.go Updates caller expectations and adds coverage for contextual template output.
log/log.go Updates AllLogger docs/comments to reflect context binding responsibilities.
docs/api/log.md Documents SetContextTemplate, custom tags, and log.WithContext(c) behavior.
docs/middleware/logger.md Documents reuse of tag/template approach for application logging.
docs/whats_new.md Adds “What’s New” entry for contextual application logging templates.
ctx_interface_gen.go Updates interface docs (multipart BodyLimit notes; HTML <p> escaping note; route URL comment).
req_interface_gen.go Updates interface docs for multipart parsing/BodyLimit enforcement.
res_interface_gen.go Updates interface docs (HTML <p> escaping note; route URL comment).

Comment thread internal/logtemplate/errors.go Outdated
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.

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
middleware/logger/default_logger.go (1)

119-123: ⚠️ Potential issue | 🟡 Minor

Test coverage for the error-append path (lines 121–123) appears to be missing.

ExecuteChains correctly short-circuits on the first error and returns it, allowing the error string to be appended to the buffer. This matches the short-circuit semantics of the previous manual chain iteration. However, no test currently exercises the error path where a function in LogFuncChain or a buffer write within ExecuteChains fails. The existing error output tests (Test_Logger_ErrorOutput*) exercise stream write failures only, not template execution failures. Consider adding a test case that injects a failing LogFunc or wraps the buffer to trigger an error inside ExecuteChains, then verifies the error message is correctly appended to the log output.

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

In `@middleware/logger/default_logger.go` around lines 119 - 123, Add a unit test
that exercises the error-append path of ExecuteChains by injecting a failing
LogFunc or a writer that errors during ExecuteChains and asserting the returned
error string is appended to the log buffer; specifically, create a test (e.g.,
Test_Logger_ErrorOutput_TemplateFailure) that builds a Logger config with a
LogFuncChain containing a function that returns an error (or wraps the buffer
with an io.Writer whose Write returns an error), call logtemplate.ExecuteChains
(via the logger flow used in existing Test_Logger_ErrorOutput* tests), capture
the buffer output and the error, and assert the buffer contains err.Error() as
appended text to validate the error-append behavior in default_logger.go.
🧹 Nitpick comments (2)
middleware/logger/logger.go (1)

100-101: TemplateChain / LogFuncChain are written into the pooled Data on every request — confirm no consumer mutates them.

Both fields share the same underlying slices across all requests. The default logger now passes them straight to logtemplate.ExecuteChains, which only reads, so this is safe today. Worth a brief note in Data's GoDoc that custom LoggerFunc implementations must treat these slices as read-only, since mutation would corrupt every subsequent request.

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

In `@middleware/logger/logger.go` around lines 100 - 101, The Data struct's
TemplateChain and LogFuncChain fields are shared pooled slices and must be
treated as read-only by consumers; update the GoDoc for type Data to explicitly
state that TemplateChain and LogFuncChain are shared across requests and must
not be mutated by custom LoggerFunc implementations (they may only
read/iterate), and add a short comment near the assignment site (where
data.TemplateChain and data.LogFuncChain are set) referencing
logtemplate.ExecuteChains as the current reader to make the expectation clear.
log/context.go (1)

35-48: Consider returning the build error instead of panicking.

SetContextTemplate panics if logtemplate.Build rejects the format string. For a library setter API this is unusual — callers typically expect Set* functions to be infallible or to return an error. Panicking forces users to either validate the format themselves or wrap calls in recover(). Since this is a brand-new API, the signature change is essentially free.

♻️ Suggested change to return an error
-// SetContextTemplate configures contextual fields rendered by WithContext for Fiber's default logger.
-func SetContextTemplate(config ContextConfig) {
+// SetContextTemplate configures contextual fields rendered by WithContext for Fiber's default logger.
+// It returns an error if config.Format cannot be parsed.
+func SetContextTemplate(config ContextConfig) error {
 	if config.Format == "" {
 		contextTemplate.Store(nil)
-		return
+		return nil
 	}
 
 	tmpl, err := logtemplate.Build[context.Context, ContextData](config.Format, createContextTagMap(config.CustomTags))
 	if err != nil {
-		panic(err)
+		return err
 	}
 
 	contextTemplate.Store(tmpl)
+	return nil
 }

If a panicking variant is still desirable, consider a MustSetContextTemplate wrapper following the standard library text/template.Must convention.

Please confirm whether the panic-on-error semantics is intentional (e.g., to surface misconfiguration loudly at startup) and double-check whether any of the new docs/examples in docs/api/log.md already advertise this signature, since changing it would require a docs update.

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

In `@log/context.go` around lines 35 - 48, Change SetContextTemplate to return an
error instead of panicking: call logtemplate.Build inside SetContextTemplate,
and if it returns an error, return that error to the caller; on success store
the template into contextTemplate via contextTemplate.Store(tmpl) and return
nil. Keep the current panic behavior as an optional MustSetContextTemplate
wrapper (e.g., MustSetContextTemplate calls SetContextTemplate and panics on
non-nil error) if you want a loud-startup variant. Update references to
SetContextTemplate callers to handle the returned error.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@log/default.go`:
- Around line 227-242: The writeContext function currently executes the template
directly into the provided buf which can leave a partial render if tmpl.Execute
fails; change writeContext to first load the template (contextTemplate.Load) and
execute it into a temporary/scratch buffer (local Buffer or bytes buffer)
instead of writing straight into l's buf, and only append the scratch buffer to
buf if tmpl.Execute succeeds; if Execute returns an error, avoid appending the
partial content and surface the failure once via an internal logger or write a
safe fixed fallback (e.g., omit context or write "[context error]"), referencing
the writeContext method, tmpl.Execute call, the contextTemplate.Load usage, and
ContextData so you modify the same symbols.

---

Outside diff comments:
In `@middleware/logger/default_logger.go`:
- Around line 119-123: Add a unit test that exercises the error-append path of
ExecuteChains by injecting a failing LogFunc or a writer that errors during
ExecuteChains and asserting the returned error string is appended to the log
buffer; specifically, create a test (e.g.,
Test_Logger_ErrorOutput_TemplateFailure) that builds a Logger config with a
LogFuncChain containing a function that returns an error (or wraps the buffer
with an io.Writer whose Write returns an error), call logtemplate.ExecuteChains
(via the logger flow used in existing Test_Logger_ErrorOutput* tests), capture
the buffer output and the error, and assert the buffer contains err.Error() as
appended text to validate the error-append behavior in default_logger.go.

---

Nitpick comments:
In `@log/context.go`:
- Around line 35-48: Change SetContextTemplate to return an error instead of
panicking: call logtemplate.Build inside SetContextTemplate, and if it returns
an error, return that error to the caller; on success store the template into
contextTemplate via contextTemplate.Store(tmpl) and return nil. Keep the current
panic behavior as an optional MustSetContextTemplate wrapper (e.g.,
MustSetContextTemplate calls SetContextTemplate and panics on non-nil error) if
you want a loud-startup variant. Update references to SetContextTemplate callers
to handle the returned error.

In `@middleware/logger/logger.go`:
- Around line 100-101: The Data struct's TemplateChain and LogFuncChain fields
are shared pooled slices and must be treated as read-only by consumers; update
the GoDoc for type Data to explicitly state that TemplateChain and LogFuncChain
are shared across requests and must not be mutated by custom LoggerFunc
implementations (they may only read/iterate), and add a short comment near the
assignment site (where data.TemplateChain and data.LogFuncChain are set)
referencing logtemplate.ExecuteChains as the current reader to make the
expectation clear.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 643b9135-e9a2-48a3-9006-9aef019af8fd

📥 Commits

Reviewing files that changed from the base of the PR and between 16d7bc1 and bba8c4c.

📒 Files selected for processing (20)
  • ctx_interface_gen.go
  • docs/api/log.md
  • docs/middleware/logger.md
  • docs/whats_new.md
  • internal/logtemplate/errors.go
  • internal/logtemplate/template.go
  • internal/logtemplate/template_test.go
  • log/context.go
  • log/context_test.go
  • log/default.go
  • log/default_test.go
  • log/log.go
  • middleware/logger/config.go
  • middleware/logger/default_logger.go
  • middleware/logger/errors.go
  • middleware/logger/logger.go
  • middleware/logger/logger_test.go
  • middleware/logger/template_chain.go
  • req_interface_gen.go
  • res_interface_gen.go
💤 Files with no reviewable changes (1)
  • middleware/logger/template_chain.go

Comment thread log/default.go
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

⚠️ Performance Alert ⚠️

Possible performance regression was detected for benchmark.
Benchmark result of this commit is worse than the previous benchmark result exceeding threshold 1.50.

Benchmark suite Current: 696dcbc Previous: 2b45a43 Ratio
Benchmark_Compress/Zstd (github.com/gofiber/fiber/v3/middleware/compress) - B/op 1 B/op 0 B/op +∞
Benchmark_Compress_Levels/Zstd_LevelDefault (github.com/gofiber/fiber/v3/middleware/compress) - B/op 1 B/op 0 B/op +∞
Benchmark_Compress_Levels/Zstd_LevelBestCompression (github.com/gofiber/fiber/v3/middleware/compress) - B/op 1 B/op 0 B/op +∞

This comment was automatically generated by workflow using github-action-benchmark.

@ReneWerner87 ReneWerner87 marked this pull request as ready for review April 29, 2026 07:12
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.

Actionable comments posted: 2

🧹 Nitpick comments (2)
docs/middleware/logger.md (1)

57-75: Consider adding a type assertion in the example for safety.

The requestid.FromContext(c) call at line 64 receives c any, but requestid.FromContext likely expects fiber.Ctx. While this works at runtime when c is actually a fiber.Ctx, adding a type assertion makes the example clearer and more defensive.

💡 Suggested improvement
     CustomTags: map[string]log.ContextTagFunc{
         "requestid": func(output log.Buffer, c any, _ *log.ContextData, _ string) (int, error) {
-            return output.WriteString(requestid.FromContext(c))
+            if fiberCtx, ok := c.(fiber.Ctx); ok {
+                return output.WriteString(requestid.FromContext(fiberCtx))
+            }
+            return 0, nil
         },
     },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/middleware/logger.md` around lines 57 - 75, Update the CustomTags
requestid tag function to perform a type assertion on the incoming c (the
parameter passed to log.ContextTagFunc) before calling requestid.FromContext:
inside the anonymous function in log.SetContextTemplate's CustomTags map assert
c to the expected type (e.g., fiber.Ctx or *fiber.Ctx depending on your app),
check the ok boolean, and call requestid.FromContext only when the assertion
succeeds (returning a sensible fallback like an empty string when it fails) so
requestid.FromContext is never invoked with an unexpected type.
log/context.go (1)

58-77: Custom tags can silently override the built-in value: tag.

maps.Copy(tags, customTags) overwrites entries if a user provides a custom tag named "value:". If this is intentional to allow overriding, consider documenting it in ContextConfig.CustomTags. If not, consider validating or warning.

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

In `@log/context.go` around lines 58 - 77, createContextTagMap currently uses
maps.Copy(tags, customTags) which lets a custom tag named TagContextValue
("value:") silently override the built-in handler; update createContextTagMap to
detect if customTags contains TagContextValue and either (a) prevent/ignore that
key (retain the built-in TagContextValue) or (b) log/warn the user and then
decide whether to override, and reflect this behavior in
ContextConfig.CustomTags docs; specifically modify the logic around
maps.Copy(tags, customTags) in createContextTagMap to check for the presence of
TagContextValue in customTags and handle it according to chosen policy,
referencing TagContextValue, createContextTagMap, and ContextConfig.CustomTags.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@log/default_test.go`:
- Around line 123-153: This test (Test_WithContextTemplate) is missing
t.Parallel() per conventions; either add t.Parallel() as the first executable
statement in the test to allow parallel execution (keep the existing t.Cleanup
that calls MustSetContextTemplate(ContextConfig{}) so global state is restored),
or if you determine shared global state (SetContextTemplate /
MustSetContextTemplate) cannot be safely parallelized, add a brief comment above
the Test_WithContextTemplate declaration explaining why it must run serially and
do not call t.Parallel(); reference SetContextTemplate, MustSetContextTemplate,
t.Cleanup and initDefaultLogger when making the change.
- Around line 155-177: Add t.Parallel() as the first line of
Test_WithContextTemplateFailureOmitsPartialContext, and remove the in-callback
test assertion; inside the ContextTagFunc implementation (the anonymous func
passed in CustomTags) replace require.NoError(t, err) with explicit error
handling that returns the write error (e.g., if err != nil { return 0, err }) so
the tag propagates the write failure instead of asserting inside the callback;
keep the rest of the test (SetContextTemplate, cleanup, SetOutput,
WithContext().Info and the final require.Equal) unchanged.

---

Nitpick comments:
In `@docs/middleware/logger.md`:
- Around line 57-75: Update the CustomTags requestid tag function to perform a
type assertion on the incoming c (the parameter passed to log.ContextTagFunc)
before calling requestid.FromContext: inside the anonymous function in
log.SetContextTemplate's CustomTags map assert c to the expected type (e.g.,
fiber.Ctx or *fiber.Ctx depending on your app), check the ok boolean, and call
requestid.FromContext only when the assertion succeeds (returning a sensible
fallback like an empty string when it fails) so requestid.FromContext is never
invoked with an unexpected type.

In `@log/context.go`:
- Around line 58-77: createContextTagMap currently uses maps.Copy(tags,
customTags) which lets a custom tag named TagContextValue ("value:") silently
override the built-in handler; update createContextTagMap to detect if
customTags contains TagContextValue and either (a) prevent/ignore that key
(retain the built-in TagContextValue) or (b) log/warn the user and then decide
whether to override, and reflect this behavior in ContextConfig.CustomTags docs;
specifically modify the logic around maps.Copy(tags, customTags) in
createContextTagMap to check for the presence of TagContextValue in customTags
and handle it according to chosen policy, referencing TagContextValue,
createContextTagMap, and ContextConfig.CustomTags.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: bcdd49fc-4694-4c27-8d24-ea48ea8aa257

📥 Commits

Reviewing files that changed from the base of the PR and between bba8c4c and 8323c21.

📒 Files selected for processing (15)
  • docs/api/log.md
  • docs/middleware/logger.md
  • docs/whats_new.md
  • internal/logtemplate/errors.go
  • internal/logtemplate/template.go
  • log/context.go
  • log/context_test.go
  • log/default.go
  • log/default_test.go
  • log/fiberlog.go
  • log/log.go
  • middleware/logger/data.go
  • middleware/logger/errors.go
  • middleware/logger/logger.go
  • middleware/logger/logger_test.go
✅ Files skipped from review due to trivial changes (1)
  • middleware/logger/data.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • internal/logtemplate/errors.go
  • log/log.go
  • docs/whats_new.md
  • internal/logtemplate/template.go

Comment thread log/default_test.go
Comment thread log/default_test.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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@log/default.go`:
- Around line 263-270: The WithContext method on defaultLogger currently calls
newRetainedContext(ctx) but always decrements depth (depth: l.depth - 1) even
when newRetainedContext(nil) returns nil; change WithContext (and references to
newRetainedContext) to retain the original l.depth unless a non-nil retained
context is returned — i.e., obtain rc := newRetainedContext(ctx) and set ctx: rc
and depth to l.depth-1 only when rc != nil, otherwise keep depth: l.depth.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a3446fb3-8d0d-418d-bf8d-cffd6d7ec707

📥 Commits

Reviewing files that changed from the base of the PR and between 8323c21 and 0e3b43c.

📒 Files selected for processing (1)
  • log/default.go

Comment thread log/default.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.

🧹 Nitpick comments (1)
log/default_test.go (1)

33-62: Document or isolate the shared logger state in these caller tests.

Test_WithContextCaller and Test_WithContextNilCaller both reassign package-global logger/output, but they neither call t.Parallel() nor explain why they must stay serial. Please either add a small cleanup/reset hook or a brief serial-execution note.

♻️ Suggested cleanup
 func Test_WithContextCaller(t *testing.T) {
+	t.Cleanup(initDefaultLogger)
 	logger = &defaultLogger{
 		stdlog: log.New(os.Stderr, "", log.Lshortfile),
 		depth:  4,
 	}
@@
 func Test_WithContextNilCaller(t *testing.T) {
+	t.Cleanup(initDefaultLogger)
 	logger = &defaultLogger{
 		stdlog: log.New(os.Stderr, "", log.Lshortfile),
 		depth:  4,
 	}

As per coding guidelines, **/*_test.go should invoke t.Parallel() at the start of each test and subtest when safe.

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

In `@log/default_test.go` around lines 33 - 62, Tests Test_WithContextCaller and
Test_WithContextNilCaller mutate package-global logger and output (logger,
SetOutput) without isolating state; either mark them serial with a comment or,
better, restore global state: at start of each test call t.Parallel() only if
you make logger/output local or add a defer to save and restore the original
logger and output after the test (capture current logger and writer, then defer
restore), ensuring WithContext calls and Info assertions run against the
isolated state; reference the functions/vars logger, SetOutput, WithContext,
Info, Test_WithContextCaller, and Test_WithContextNilCaller when applying the
fix.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@log/default_test.go`:
- Around line 33-62: Tests Test_WithContextCaller and Test_WithContextNilCaller
mutate package-global logger and output (logger, SetOutput) without isolating
state; either mark them serial with a comment or, better, restore global state:
at start of each test call t.Parallel() only if you make logger/output local or
add a defer to save and restore the original logger and output after the test
(capture current logger and writer, then defer restore), ensuring WithContext
calls and Info assertions run against the isolated state; reference the
functions/vars logger, SetOutput, WithContext, Info, Test_WithContextCaller, and
Test_WithContextNilCaller when applying the fix.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 8a0d7125-367e-4402-8eb8-3ccbde4db39b

📥 Commits

Reviewing files that changed from the base of the PR and between 0e3b43c and c3aa623.

📒 Files selected for processing (1)
  • log/default_test.go

@ReneWerner87 ReneWerner87 marked this pull request as draft April 30, 2026 19:53
@ReneWerner87 ReneWerner87 requested a review from Copilot April 30, 2026 20:27
@ReneWerner87
Copy link
Copy Markdown
Member Author

/gemini review

@ReneWerner87
Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 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

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a unified log template mechanism via a new internal logtemplate package, which is now utilized by both the application logger and the access logger middleware. A key feature is the introduction of global context tag registration, allowing middleware like requestid, basicauth, and session to automatically register tags that can be rendered in logs when using log.WithContext(ctx). The PR also includes extensive documentation updates and refactors the log package to support any context types. Review feedback suggests improving documentation examples for type safety and clarity, correcting markdown syntax for callouts, and ensuring consistent error handling for unknown tags within the template parser.

Comment thread docs/api/log.md Outdated
Comment thread docs/middleware/logger.md
Comment thread docs/whats_new.md
Comment thread internal/logtemplate/template.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 30 out of 30 changed files in this pull request and generated 1 comment.

Comment thread middleware/requestid/requestid.go Outdated
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.

Actionable comments posted: 2

🧹 Nitpick comments (1)
middleware/keyauth/keyauth.go (1)

120-125: 💤 Low value

Minor inconsistency: redactContextValue doesn't handle empty strings the same way as session's redactSessionID.

The callers guard against empty strings before calling this function, so there's no bug. However, redactSessionID in the session middleware explicitly returns "" for empty input, while this function would return "****" for an empty string if called directly.

Consider aligning for defensive consistency:

♻️ Optional alignment
 func redactContextValue(value string) string {
+	if value == "" {
+		return ""
+	}
 	if len(value) <= 4 {
 		return "****"
 	}
 	return value[:4] + "****"
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@middleware/keyauth/keyauth.go` around lines 120 - 125, redactContextValue
currently returns "****" for empty input, which is inconsistent with
session.middleware's redactSessionID that returns "" for empty strings; update
redactContextValue (the function named redactContextValue) to return an empty
string when value == "" and otherwise preserve the existing redaction logic so
callers behave consistently and the function is defensive if called directly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/api/log.md`:
- Around line 248-250: The example for log.MustRegisterContextTag uses an unsafe
type assertion on ctx to fiber.Ctx which can panic; update the tag handler in
log.MustRegisterContextTag to perform a safe type assertion (e.g., c, ok :=
ctx.(fiber.Ctx) or pointer variant) and handle the false case by writing a
default/empty tenant or returning 0,nil, and also guard access to
c.Locals("tenant") before asserting it to string so the tenant value is safely
read and written to output without panicking.

In `@middleware/logger/logger_test.go`:
- Around line 1062-1075: The LoggerFunc currently calls require.* inside the
handler (LoggerFunc) — remove those testing assertions and instead return
explicit errors from LoggerFunc when validations fail or writes error (e.g., if
len mismatch, return fmt.Errorf("template/log func chain length mismatch: got %d
vs %d", ...); on buf.Write or logFunc(...) errors return that error directly).
Keep using the existing LoggerFunc signature (func(c fiber.Ctx, data *Data, _
*Config) error) and propagate the first encountered error out; then after
calling app.Test in the test, assert on the returned error and validate
TemplateChain/LogFuncChain lengths and write results with
require/require.NoError there (outside the handler).

---

Nitpick comments:
In `@middleware/keyauth/keyauth.go`:
- Around line 120-125: redactContextValue currently returns "****" for empty
input, which is inconsistent with session.middleware's redactSessionID that
returns "" for empty strings; update redactContextValue (the function named
redactContextValue) to return an empty string when value == "" and otherwise
preserve the existing redaction logic so callers behave consistently and the
function is defensive if called directly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: a39fbfde-c768-492f-9cb2-5d438c351d73

📥 Commits

Reviewing files that changed from the base of the PR and between c3aa623 and 94ac462.

📒 Files selected for processing (16)
  • docs/api/log.md
  • docs/middleware/logger.md
  • log/context.go
  • log/context_test.go
  • log/default.go
  • log/default_test.go
  • middleware/basicauth/basicauth.go
  • middleware/csrf/csrf.go
  • middleware/keyauth/keyauth.go
  • middleware/logger/config.go
  • middleware/logger/errors_test.go
  • middleware/logger/logger_test.go
  • middleware/logger/tags.go
  • middleware/requestid/requestid.go
  • middleware/requestid/requestid_test.go
  • middleware/session/middleware.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • middleware/logger/errors_test.go
  • log/default_test.go

Comment thread docs/api/log.md
Comment thread middleware/logger/logger_test.go
@gaby gaby changed the title feat: reuse logger template rendering for contextual logs 🔥 feat: Add support for contextual logs May 1, 2026
@gaby gaby moved this to In Progress in v3 May 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

🤗 [Question]: About fiber v3 log

3 participants