Skip to content

feat(log): support generic configurable logger#3705

Merged
ReneWerner87 merged 7 commits intomainfrom
codex/2025-08-23-13-18-21
Aug 24, 2025
Merged

feat(log): support generic configurable logger#3705
ReneWerner87 merged 7 commits intomainfrom
codex/2025-08-23-13-18-21

Conversation

@ReneWerner87
Copy link
Member

Summary

  • add baseLogger interface so default loggers of any type can be stored
  • return concrete logger from Logger() and make DefaultLogger/SetLogger generic
  • generalize LoggerToWriter helper and document typed logger usage

Testing

  • make audit (fails: EncodeMsg passes lock by value)
  • make generate
  • make betteralign (fails: package requires newer Go version go1.25)
  • make modernize (fails: package requires newer Go version go1.25)
  • make format
  • make test

https://chatgpt.com/codex/tasks/task_e_68a9b76433788326b13092e0c67f49e8

Copilot AI review requested due to automatic review settings August 23, 2025 13:18
@ReneWerner87 ReneWerner87 requested a review from a team as a code owner August 23, 2025 13:18
@ReneWerner87 ReneWerner87 requested a review from gaby August 23, 2025 13:18
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 23, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Warning

Rate limit exceeded

@ReneWerner87 has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 12 minutes and 16 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.

📥 Commits

Reviewing files that changed from the base of the PR and between bb36b1c and e0264d9.

📒 Files selected for processing (3)
  • client/client.go (1 hunks)
  • docs/whats_new.md (3 hunks)
  • middleware/logger/logger_test.go (4 hunks)

Walkthrough

Introduces generics to the logging surface: AllLogger and ConfigurableLogger become generic, Logger() returns the type parameter, DefaultLogger/SetLogger gain type parameters, and middleware helpers (e.g., LoggerToWriter) are updated. Tests, docs, and client init updated to the typed API.

Changes

Cohort / File(s) Summary of Changes
Client init update
client/client.go
Switched logger initialization to generic form: log.DefaultLogger[any]().
Core logging types & globals
log/log.go, log/default.go, log/fiberlog.go
Converted ConfigurableLogger and AllLogger to generics ([T any]), changed Logger() anyLogger() T, introduced internal baseLogger for global storage, and made DefaultLogger/SetLogger generic. Adjusted default logger assertions to AllLogger[*log.Logger].
Core tests
log/default_test.go, log/fiberlog_test.go
Replaced non-generic calls with DefaultLogger[*log.Logger]() and removed runtime type assertions by using the typed Logger() return.
Middleware logger API & utils
middleware/logger/logger.go, middleware/logger/utils.go
Made middleware-facing Logger, DefaultLogger, and LoggerToWriter generic ([T any]); adapted internal writer type to customLoggerWriter[T].
Middleware tests/benchmarks
middleware/logger/logger_test.go
Updated tests/benchmarks to call DefaultLogger[...]() and to use typed Logger(); updated LoggerToWriter invocations to generic form.
Docs & migration notes
docs/api/log.md, docs/whats_new.md
Added generic API docs and examples (AllLogger[*log.Logger], SetLogger[*log.Logger], DefaultLogger[*log.Logger](), typed Logger()), added ForceColors config mention, and updated migration guidance.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor App
  participant LogPkg as log package
  participant Def as defaultLogger
  participant MW as middleware/logger

  App->>LogPkg: DefaultLogger[*log.Logger]()
  activate LogPkg
  LogPkg->>Def: construct/return singleton (typed)
  Def-->>LogPkg: AllLogger[*log.Logger]
  LogPkg-->>App: AllLogger[*log.Logger]
  deactivate LogPkg

  App->>LogPkg: SetLogger[*log.Logger](logger)
  LogPkg-->>App: stored as baseLogger

  App->>MW: LoggerToWriter[*log.Logger](logger, level)
  MW-->>App: io.Writer (typed wrapper)

  App->>logger: Logger()
  logger-->>App: *log.Logger (typed)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

v3

Suggested reviewers

  • gaby
  • sixcolors
  • efectn
  • grivera64

Poem

I nibbled through types with a hop and a cheer,
Turned Logger to generics, the path is now clear.
No casts, just returns that match what you wrote —
Carrots for tests and docs tied with a note.
Bunny says: hop on, the logs stay afloat. 🥕🐇

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/2025-08-23-13-18-21

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
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.

Summary of Changes

Hello @ReneWerner87, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the logging system by leveraging Go generics. The primary goal is to provide a more flexible and type-safe way to configure and interact with loggers, allowing users to seamlessly integrate various logging libraries while maintaining strong type guarantees. This involves making key logger interfaces and functions generic, introducing an internal base logger interface for better management, and updating documentation to reflect these changes.

Highlights

  • Generic Logger Interfaces: The AllLogger and ConfigurableLogger interfaces are now generic, enabling type-safe handling of different underlying logger implementations.
  • Type-Safe Logger Access: The DefaultLogger() and SetLogger() functions are updated to be generic, allowing direct retrieval and setting of concrete logger types without manual type assertions.
  • Internal Logger Management: A new baseLogger interface is introduced to internally manage diverse logger implementations, improving the system's robustness.
  • Streamlined Logger Integration: The LoggerToWriter helper function is generalized with generics, simplifying the integration of third-party loggers with the middleware.
  • Comprehensive Documentation: The documentation in docs/api/log.md and docs/whats_new.md has been updated to provide clear guidance and examples for utilizing the new generic logging capabilities.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
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 adds generic type support to the Fiber logging system, enabling better type safety when working with custom loggers. The changes introduce a new baseLogger interface for internal use while making the public logging interfaces generic to support typed logger instances.

  • Introduces generic type parameters to ConfigurableLogger and AllLogger interfaces
  • Updates SetLogger and DefaultLogger functions to work with generic types
  • Generalizes the LoggerToWriter utility function to support typed loggers

Reviewed Changes

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

Show a summary per file
File Description
log/log.go Adds baseLogger interface and makes ConfigurableLogger and AllLogger generic
log/fiberlog.go Updates SetLogger function to accept generic logger types
log/default.go Makes DefaultLogger generic and updates Logger() method return type
middleware/logger/utils.go Generalizes LoggerToWriter and related types to support generic loggers
middleware/logger/logger_test.go Updates test code to use generic logger types
log/fiberlog_test.go Updates test code to use generic logger types
log/default_test.go Removes unnecessary type assertion in test
client/client.go Updates client initialization to use generic logger
docs/api/log.md Updates documentation to reflect generic logger usage
docs/whats_new.md Adds migration notes for the generic logger changes

@codecov
Copy link

codecov bot commented Aug 23, 2025

Codecov Report

❌ Patch coverage is 90.90909% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 91.79%. Comparing base (edd7083) to head (e0264d9).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
log/default.go 83.33% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3705      +/-   ##
==========================================
- Coverage   91.79%   91.79%   -0.01%     
==========================================
  Files         114      114              
  Lines       11536    11539       +3     
==========================================
+ Hits        10590    10592       +2     
- Misses        684      685       +1     
  Partials      262      262              
Flag Coverage Δ
unittests 91.79% <90.90%> (-0.01%) ⬇️

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.

Copy link
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 generic logger interface to allow retrieving the concrete logger instance, which is a great enhancement for flexibility. The changes are well-reflected in the documentation and tests.

However, there's a critical issue in the implementation of log.DefaultLogger where a failing type assertion is not handled, which can lead to panics. Additionally, there are several places where DefaultLogger[any]() is used, which seems to stem from a misunderstanding of how Go generics work with interfaces and will cause the application to panic. I've provided comments and suggestions to fix these issues. There's also a minor point about clarifying the use of generics in the whats_new.md documentation to avoid confusion for users.

Copy link
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 (6)
docs/whats_new.md (1)

1168-1171: Inconsistent comment: says “zerolog” but example uses zap

The snippet creates a zap logger (fiberzap.NewLogger), but the comment says “zerolog”. Update the comment to “zap” to avoid confusion.

-    // Use the logger middleware with zerolog logger
+    // Use the logger middleware with zap logger
docs/api/log.md (1)

159-163: Broken example: uses unexported defaultLogger and won’t compile

This snippet references defaultLogger, which is unexported and not available to users. Also, constructing it directly bypasses the intended API surface. Replace with the public functions.

-// Writing Logs to Stderr
-// (broken: uses unexported type)
-var logger fiberlog.AllLogger[*log.Logger] = &defaultLogger{
-    stdlog: log.New(os.Stderr, "", log.LstdFlags|log.Lshortfile|log.Lmicroseconds),
-    depth:  4,
-}
+// Writing Logs to Stderr (correct)
+fiberlog.SetOutput(os.Stderr)
+// Optionally adjust std logger flags
+std := fiberlog.DefaultLogger[*log.Logger]().Logger()
+std.SetFlags(log.LstdFlags | log.Lshortfile | log.Lmicroseconds)
client/client.go (1)

33-34: Fix logger initializer to match its declared interface

The Client struct declares its logger field as a log.CommonLogger, but the initializer in NewWithClient uses the generic call log.DefaultLogger[any](), which returns an AllLogger[any]. Since our default implementation (defaultLogger) only satisfies AllLogger[*log.Logger], the type assertion inside DefaultLogger[any]() fails and yields nil, leading to a broken logger at runtime.

To resolve, specialize the type parameter to the concrete *log.Logger so that the returned value truly implements CommonLogger:

• In client/client.go, around line 665, change the initializer:

-   logger: log.DefaultLogger[any](),
+   logger: log.DefaultLogger[*log.Logger](),

• This ensures DefaultLogger[*log.Logger]() returns an AllLogger[*log.Logger], which embeds CommonLogger and matches your field.

Additionally, scan the codebase for any other uses of DefaultLogger[any]() (e.g., in middleware tests at middleware/logger/logger_test.go:1105 and 1261) and either:

  • Update them to DefaultLogger[*log.Logger](), or
  • Change the receiving field to accept AllLogger[any].
log/fiberlog.go (1)

73-76: Docstring typo: Panicf comment references Tracef

The comment says “Panicf calls the default logger's Tracef method,” which is incorrect and misleading for users of this API.

Apply this diff to fix the docstring:

-// Panicf calls the default logger's Tracef method.
+// Panicf calls the default logger's Panicf method.
middleware/logger/utils.go (1)

50-67: Default case returns (0, nil); prefer reporting full consumption or error

Returning (0, nil) from Write may cause callers to retry or mis-handle partial writes. Since invalid levels are filtered earlier, default should either consume all bytes or return an error.

Apply this diff:

 	default:
-		return 0, nil
+		// Treat as a no-op but signal full consumption to avoid retry loops.
+		return len(p), nil
 	}

Alternatively, return 0 and a concrete error (but that would propagate into middleware paths).

log/default.go (1)

55-59: privateLogf bug: empty arg slice drops the format string

When no args are provided, the else path calls Fprint with fmtArgs (empty), resulting in an empty message instead of the format string.

Apply this fix:

-	if len(fmtArgs) > 0 {
-		_, _ = fmt.Fprintf(buf, format, fmtArgs...)
-	} else {
-		_, _ = fmt.Fprint(buf, fmtArgs...)
-	}
+	if len(fmtArgs) > 0 {
+		_, _ = fmt.Fprintf(buf, format, fmtArgs...)
+	} else {
+		buf.WriteString(format)
+	}

Add a unit test to cover Infof("msg") without args.

🧹 Nitpick comments (16)
log/log.go (3)

11-18: Solid internal abstraction, but consider documenting variance limitations

Defining a non-generic baseLogger lets you keep a single global while exposing generics publicly. Please add a short note in the comment that values stored in logger must implement AllLogger[T] for their concrete T (no covariance), so callers should not expect DefaultLogger[any]() to succeed. This will preempt misuse down the line.


80-86: Consider a typed variant of WithContext for power users

WithContext(ctx) CommonLogger preserves the old surface, but it discards the type information. Consider adding an optional WithContextT[T any](ctx) AllLogger[T] (or a method on concrete implementations) so users can still access typed underlying loggers after binding a context.


104-119: Minor naming nit: strs -> levelPrefixes

strs is a bit vague. A more descriptive name would improve readability.

- var strs = []string{
+ var levelPrefixes = []string{
@@
-func (lv Level) toString() string {
+func (lv Level) toString() string {
-   if lv >= LevelTrace && lv <= LevelPanic {
-       return strs[lv]
+   if lv >= LevelTrace && lv <= LevelPanic {
+       return levelPrefixes[lv]
    }
docs/whats_new.md (1)

1881-1884: Add a caution about generics variance to prevent misuse

Please add a one-liner that AllLogger[T] is not covariant: implementations usually satisfy AllLogger[*log.Logger] (std lib), not AllLogger[any]. Users should use the concrete underlying type (e.g., *log.Logger) when calling DefaultLogger[T].

 #### 🧾 Log
-
-The `ConfigurableLogger` and `AllLogger` interfaces now use generics. You can specify the underlying logger type when implementing these interfaces or use `any` for maximum flexibility. `log.SetLogger` and `log.DefaultLogger` also accept a type parameter, so the concrete logger can be retrieved and used directly, for example `log.DefaultLogger[*MyLogger]().Logger()`.
+The `ConfigurableLogger` and `AllLogger` interfaces now use generics. Specify the concrete underlying logger type (e.g., `*log.Logger`) when implementing or retrieving defaults. Note: `AllLogger[T]` is not covariant—using `any` as `T` will not match implementations built for a concrete `T`. `log.SetLogger` and `log.DefaultLogger` accept a type parameter; for example, `log.DefaultLogger[*log.Logger]().Logger()`.
docs/api/log.md (1)

28-53: Interfaces look correct; minor duplication

Turning ConfigurableLogger and AllLogger into generics is on point. Note AllLogger[T] embeds CommonLogger (which already embeds WithLogger), so the extra WithLogger line in AllLogger[T] is redundant. Not wrong, just repetitive.

 type AllLogger[T any] interface {
     CommonLogger
     ConfigurableLogger[T]
-    WithLogger
 }
log/fiberlog.go (3)

78-82: Clarify repetitive “w”-method docstrings

The phrase “pairs are treated as they are privateLog With.” is awkward and unclear across Tracew/Debugw/Infow/Warnw/Errorw/Fatalw/Panicw. Suggest a concise, consistent phrasing.

Example diff for one occurrence (apply similarly to all “w” variants):

-// Tracew logs a message with some additional context. The variadic key-value
-// pairs are treated as they are privateLog With.
+// Tracew logs a message with additional key-value context (same semantics as With).

Also applies to: 84-88, 90-94, 96-100, 102-106, 108-112, 114-118


126-129: SetLogger is not concurrency-safe; benches call it in parallel

The comment correctly states non-concurrency-safety. However, Benchmark_SetLogger_Parallel exercises SetLogger concurrently in tests, which will race under -race. Consider keeping the benchmark but add a note or a build tag to skip with -race, or make the global swap atomic if you want to support concurrent reconfiguration.

Option A: Keep as-is, add a clarifying comment in the benchmark.
Option B (heavier): Use atomic.Value for the global logger to make swaps race-free.

If you want to explore Option B later, I can draft it behind an internal helper to avoid public API changes.


120-122: Typed WithContext returns CommonLogger — document type erasure

WithContext returns CommonLogger (non-generic), which erases the type parameter. That’s fine per log.go’s interface, but please ensure docs mention that typed accessors (like Logger()) won’t be available on the returned value.

log/fiberlog_test.go (2)

149-162: Parallel SetLogger will race under -race

This intentionally stresses SetLogger, but it will deterministically flag a data race under -race (as documented by the API). Consider skipping this benchmark when -race is enabled.

Apply this diff to add a guard:

 func Benchmark_SetLogger_Parallel(b *testing.B) {
+	if raceEnabled() { // helper that returns true under -race, see below
+		b.Skip("SetLogger is not concurrency-safe; skip under -race")
+	}
 	setLog := &defaultLogger{
 		stdlog: log.New(os.Stderr, "", log.LstdFlags|log.Lshortfile|log.Lmicroseconds),
 		depth:  6,
 	}
@@
 	b.RunParallel(func(pb *testing.PB) {
 		for pb.Next() {
 			SetLogger(setLog)
 		}
 	})
 }
+
+// place near tests:
+func raceEnabled() bool { return false } // replaced at build-time with -tags race via a file with `package log; func raceEnabled() bool { return true }`

201-211: Parallel SetLevel mutates shared state without sync

SetLevel writes to mockLogger.level; concurrent calls can race under -race. Either keep (documented) or isolate from -race runs similar to SetLogger.

middleware/logger/utils.go (2)

45-48: Generic parameter T is unused in writer; consider narrowing to CommonLogger

customLoggerWriter[T] stores AllLogger[T] but only uses CommonLogger methods. You can simplify API and avoid unnecessary generic instantiation by accepting fiberlog.CommonLogger instead. This avoids monomorphization and reduces surface area.

Example:

-type customLoggerWriter[T any] struct {
-	loggerInstance fiberlog.AllLogger[T]
+type customLoggerWriter struct {
+	loggerInstance fiberlog.CommonLogger
 	level          fiberlog.Level
 }

And adjust LoggerToWriter accordingly (see below).


72-87: Broaden level validation to future-proof against out-of-range values

You panic for Fatal/Panic, but other invalid ints could slip through if Level gains values or callers pass arbitrary ints. Validate the permitted range explicitly.

If Level values are contiguous from LevelTrace to LevelError:

-func LoggerToWriter[T any](logger fiberlog.AllLogger[T], level fiberlog.Level) io.Writer {
+func LoggerToWriter[T any](logger fiberlog.AllLogger[T], level fiberlog.Level) io.Writer {
 	// Check if customLogger is nil
 	if logger == nil {
 		fiberlog.Panic("LoggerToWriter: customLogger must not be nil")
 	}
 
 	// Check if level is valid
-	if level == fiberlog.LevelFatal || level == fiberlog.LevelPanic {
+	if level < fiberlog.LevelTrace || level > fiberlog.LevelError {
 		fiberlog.Panic("LoggerToWriter: invalid level")
 	}
 
-	return &customLoggerWriter[T]{
+	return &customLoggerWriter[T]{
 		level:          level,
 		loggerInstance: logger,
 	}
 }

If you adopt the CommonLogger simplification, also change the return to &customLoggerWriter{...} and the argument type to fiberlog.CommonLogger.

log/default.go (3)

22-24: Docstrings: minor grammar fixes

“logs a message at a given level log the default logger.” → “logs a message at the given level using the default logger.”

-// privateLog logs a message at a given level log the default logger.
+// privateLog logs a message at the given level using the default logger.
...
-// privateLog logs a message at a given level log the default logger.
+// privateLogf logs a message at the given level using the default logger.
...
-// privateLog logs a message at a given level log the default logger.
+// privateLogw logs a message at the given level using the default logger.

Also applies to: 45-47, 72-74


29-43: Ensure pooled buffer is returned on panic paths

In privateLog/privateLogf/privateLogw, a panic occurs before the buffer is returned to the pool. Use a defer to always Reset+Put even on panic.

Apply this pattern to all three functions:

 	buf := bytebufferpool.Get()
+	defer func() {
+		buf.Reset()
+		bytebufferpool.Put(buf)
+	}()
 	buf.WriteString(level)
 	// ...
-	_ = l.stdlog.Output(l.depth, buf.String()) //nolint:errcheck // It is fine to ignore the error
-	if lv == LevelPanic {
-		panic(buf.String())
-	}
-	buf.Reset()
-	bytebufferpool.Put(buf)
+	_ = l.stdlog.Output(l.depth, buf.String()) //nolint:errcheck // It is fine to ignore the error
+	if lv == LevelPanic {
+		panic(buf.String())
+	}
 	if lv == LevelFatal {
 		os.Exit(1) //nolint:revive // we want to exit the program when Fatal is called
 	}

Note: os.Exit bypasses defers, but you already Put the buffer before Exit; keep that sequencing.

Also applies to: 51-70, 79-111


218-221: DefaultLogger: handle failed type assertion explicitly (and quiet linters)

Returning a nil typed interface when the assertion fails is fine, but being explicit improves readability and can address static analysis noise.

Apply:

-func DefaultLogger[T any]() AllLogger[T] {
-	l, _ := logger.(AllLogger[T])
-	return l
-}
+func DefaultLogger[T any]() AllLogger[T] {
+	if l, ok := logger.(AllLogger[T]); ok {
+		return l
+	}
+	return nil
+}

If errcheck flagged this line (hint suggests so), confirm the warning disappears with this change.

middleware/logger/logger_test.go (1)

1104-1110: Benchmarks use typed DefaultLogger and LoggerToWriter correctly

Good coverage for the generic path in both serial and parallel benches. If you adopt the CommonLogger simplification in LoggerToWriter, the benchmark call sites won’t need generics.

Also applies to: 1259-1265

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 5c403cd and a70230c.

📒 Files selected for processing (10)
  • client/client.go (1 hunks)
  • docs/api/log.md (6 hunks)
  • docs/whats_new.md (3 hunks)
  • log/default.go (2 hunks)
  • log/default_test.go (1 hunks)
  • log/fiberlog.go (1 hunks)
  • log/fiberlog_test.go (3 hunks)
  • log/log.go (3 hunks)
  • middleware/logger/logger_test.go (4 hunks)
  • middleware/logger/utils.go (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
docs/**

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Review and update the contents of the docs folder if necessary when modifying code

Files:

  • docs/api/log.md
  • docs/whats_new.md
🧠 Learnings (1)
📚 Learning: 2024-11-15T07:56:21.623Z
Learnt from: ReneWerner87
PR: gofiber/fiber#3161
File: app.go:923-932
Timestamp: 2024-11-15T07:56:21.623Z
Learning: In the Fiber framework, breaking changes are acceptable when moving from version 2 to version 3, including modifications to method signatures such as in the `Test` method in `app.go`.

Applied to files:

  • docs/whats_new.md
🧬 Code graph analysis (8)
client/client.go (1)
log/default.go (1)
  • DefaultLogger (219-222)
log/default.go (1)
log/log.go (2)
  • AllLogger (80-86)
  • Logger (26-34)
log/fiberlog.go (1)
log/log.go (1)
  • AllLogger (80-86)
log/default_test.go (1)
log/log.go (1)
  • Logger (26-34)
log/fiberlog_test.go (2)
log/default.go (1)
  • DefaultLogger (219-222)
log/log.go (1)
  • Logger (26-34)
middleware/logger/utils.go (1)
log/log.go (2)
  • AllLogger (80-86)
  • Level (91-91)
log/log.go (1)
log/fiberlog.go (3)
  • SetLevel (139-141)
  • SetOutput (132-134)
  • WithContext (120-122)
middleware/logger/logger_test.go (3)
log/default.go (1)
  • DefaultLogger (219-222)
log/log.go (2)
  • Logger (26-34)
  • LevelFatal (100-100)
middleware/logger/utils.go (1)
  • LoggerToWriter (73-88)
🪛 GitHub Check: lint
log/default.go

[failure] 220-220:
Error return value is not checked (errcheck)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: unit (1.25.x, macos-13)
  • GitHub Check: unit (1.25.x, windows-latest)
  • GitHub Check: unit (1.25.x, macos-latest)
  • GitHub Check: repeated
  • GitHub Check: Compare
🔇 Additional comments (16)
log/log.go (2)

20-23: Global default uses std log with rich flags — LGTM

Good defaults: stderr + LstdFlags|Lshortfile|Lmicroseconds and depth: 4.


65-76: Typed Logger() T is the right call

Changing ConfigurableLogger to ConfigurableLogger[T] with Logger() T eliminates unsafe assertions on the consumer side. Nice.

docs/whats_new.md (2)

986-989: Good overview of the new typed logger surface

Clear statement of AllLogger[T] + Logger().


1413-1413: Index update for Log migration — LGTM

Anchor aligns with the new section.

docs/api/log.md (4)

120-121: Nice compile-time guarantee

var _ fiberlog.AllLogger[*log.Logger] = (*customLogger)(nil) is a good interface guard.


129-132: Typed SetLogger example — LGTM

Using SetLogger[*log.Logger] demonstrates the generic API well.


133-136: Good: direct typed access to std logger

DefaultLogger[*log.Logger]().Logger() removing runtime assertions is exactly the benefit users need.


211-215: Typed retrieval section — LGTM

Clear and accurate.

log/default_test.go (1)

233-236: Test now reflects typed Logger() — LGTM

Dropping the runtime type assertion is correct after making Logger() return a concrete *log.Logger.

log/fiberlog_test.go (3)

13-15: Typed DefaultLogger usage LGTM

Switching to DefaultLogger*log.Logger removes runtime type assertions and is consistent with the new API.


73-78: Benchmark DefaultSystemLogger typed call LGTM

Using the typed DefaultLogger in the benchmark is consistent and keeps allocations observable.


139-147: Parallel read of DefaultLogger is fine; ensure no concurrent SetLogger during this bench

Reading the global logger concurrently is benign if no concurrent writers. Keep this bench isolated from SetLogger concurrent benches when running with -race.

log/default.go (2)

214-216: Logger() return type LGTM

Returning *log.Logger directly improves ergonomics and removes type assertions in tests and examples.


14-14: Compile-time assertion LGTM

Asserting defaultLogger implements AllLogger[*log.Logger] ensures API coherence after the generics shift.

middleware/logger/logger_test.go (2)

344-346: Typed DefaultLogger + direct std logger access LGTM

Using DefaultLogger[*log.Logger] and then Logger() avoids reflection and clarifies intent.


381-384: LoggerToWriter generic usage and panic tests LGTM

Typed invocation matches the new signature; invalid level and nil logger panics are well-covered.

Also applies to: 396-406

Copy link
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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

ReneWerner87 and others added 5 commits August 23, 2025 18:35
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Copy link
Member

@gaby gaby left a comment

Choose a reason for hiding this comment

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

LGTM

@gaby gaby added this to v3 Aug 24, 2025
@gaby gaby added this to the v3 milestone Aug 24, 2025
@gaby gaby moved this to In Progress in v3 Aug 24, 2025
@ReneWerner87 ReneWerner87 merged commit 64a7113 into main Aug 24, 2025
14 of 15 checks passed
@ReneWerner87 ReneWerner87 deleted the codex/2025-08-23-13-18-21 branch August 24, 2025 11:31
@github-project-automation github-project-automation bot moved this from In Progress to Done in v3 Aug 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants