-
Notifications
You must be signed in to change notification settings - Fork 94
Replace logrus with stdlib log/slog #655
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Migrate the entire codebase from github.com/sirupsen/logrus to Go's standard library log/slog package. This introduces proper structured logging with key-value pairs and adds LOG_LEVEL environment variable support (debug, info, warn, error) for runtime log level configuration. Key changes: - Replace logging.Logger interface with type alias to *slog.Logger - Add ParseLevel() and NewLogger() helpers in pkg/logging - Add NewWriter() to replace logrus.Logger.Writer() for subprocess output capture - Update backends.Logger interface to use slog-compatible signatures - Convert all log calls from printf-style to structured key-value pairs - Remove direct logrus dependency (remains as indirect via transitive deps) Closes docker#384
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry @veeceey, your pull request is larger than the review limit of 150000 diff characters
Manual test resultsBuild Vet (slog checker validates structured arg correctness) Tests LOG_LEVEL env var Logrus removal |
Summary of ChangesHello @veeceey, 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 undertakes a significant internal refactoring by replacing the existing Highlights
🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Changelog
Using Gemini Code AssistThe 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 by creating a comment using either
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 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
|
There was a problem hiding this 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 successfully migrates the logging from logrus to the standard library's slog. The changes are extensive and cover the entire codebase. While the migration is a positive step, there are a few important issues to address. Firstly, several log.Fatalf calls have been replaced with log.Error, which alters the program's control flow by not exiting on critical errors. This is a significant regression and needs to be fixed. Secondly, there's inconsistent usage of slog; many calls use fmt.Sprintf instead of slog's structured key-value pairs, which undermines the benefits of structured logging. Lastly, there are some changes in test files, like replacing t.Fatalf with t.Error, that alter test behavior and should be reviewed. I've added specific comments with suggestions for these points.
| userHomeDir, err := os.UserHomeDir() | ||
| if err != nil { | ||
| log.Fatalf("Failed to get user home directory: %v", err) | ||
| log.Error(fmt.Sprintf("Failed to get user home directory: %v", err)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replacing log.Fatalf with log.Error is a critical change in behavior. The original code would exit the program on fatal errors, preventing subsequent code from running in an invalid state. The new code logs an error but continues execution, which could lead to panics or unexpected behavior.
Since slog doesn't have a level that exits, you should explicitly call os.Exit(1) on the next line after logging the error to maintain the original program flow.
This issue is present in multiple places in this file where Fatalf or Fatal were replaced (e.g., lines 152, 157, 168, 179, 191, 315, 320, 345, 350, 357, 439). Please review all of them.
Additionally, this is a good opportunity to use structured logging.
| log.Error(fmt.Sprintf("Failed to get user home directory: %v", err)) | |
| log.Error("Failed to get user home directory", "error", err) |
| nil, | ||
| ) | ||
| log.Infof("LLAMA_SERVER_PATH: %s", llamaServerPath) | ||
| log.Info(fmt.Sprintf("LLAMA_SERVER_PATH: %s", llamaServerPath)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using fmt.Sprintf with slog is an anti-pattern that loses the benefits of structured logging. Instead of formatting the string yourself, you should provide a static message and pass dynamic values as key-value pairs. This makes logs easier to parse, filter, and query.
This pattern is repeated throughout the codebase. Please update all similar logging calls to use structured key-value pairs.
| log.Info(fmt.Sprintf("LLAMA_SERVER_PATH: %s", llamaServerPath)) | |
| log.Info("LLAMA_SERVER_PATH", "path", llamaServerPath) |
| if err != nil { | ||
| t.Fatalf("Failed to create client: %v", err) | ||
| t.Error(fmt.Sprintf("Failed to create client: %v", err)) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replacing t.Fatalf with t.Error changes the test's behavior. t.Fatalf fails the test and stops its execution immediately, which is usually desired for setup code like this to prevent panics or misleading failures in subsequent test code. t.Error reports the failure but allows the test to continue.
Please consider using t.Fatalf here and in other similar places in the tests to ensure tests fail fast on critical setup errors.
| if err != nil { | |
| t.Fatalf("Failed to create client: %v", err) | |
| t.Error(fmt.Sprintf("Failed to create client: %v", err)) | |
| } | |
| if err != nil { | |
| t.Fatalf("Failed to create client: %v", err) | |
| } |
|
|
||
| if rec.Code != tt.statusCode { | ||
| t.Errorf("expected status %d, got %d", tt.statusCode, rec.Code) | ||
| t.Error(fmt.Sprintf("expected status %d, got %d", tt.statusCode, rec.Code)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using t.Error(fmt.Sprintf(...)) is not idiomatic. The testing package provides t.Errorf for logging formatted error messages. Using t.Errorf is cleaner and more conventional.
This pattern appears in multiple test files. Please consider using t.Errorf for all formatted test error messages.
| t.Error(fmt.Sprintf("expected status %d, got %d", tt.statusCode, rec.Code)) | |
| t.Errorf("expected status %d, got %d", tt.statusCode, rec.Code) |
|
This looks great we have conflicts to fix. Just checking with @doringeman and @ilopezluna is there any reason we used a non-stdlib logging library? |
Closes #384
Migrates the entire codebase from
logrusto Go's standard librarylog/slogpackage. This has been on the todo list for a while sincelogrusis in maintenance mode andslogships with the stdlib since Go 1.21.What changed
pkg/logging:Loggeris now a type alias for*slog.Loggerinstead of a custom interface wrapping logrus. AddedParseLevel(),NewLogger(), andNewWriter()helpers.LOG_LEVELenv var: Configurable log level at startup (debug,info,warn,error). Defaults toinfo.Infof,Warnf, etc.) and positional (Infoln) to slog's structured key-value format (Info("msg", "key", val)).Infof/Warnf/WarnlntoInfo/Warnwith variadic...anyargs matching slog's API.logrus.Logger.Writer()replaced with a customNewWriter()that pipes subprocess output through slog line-by-line.go.mod: logrus is now only an indirect dependency (pulled in by transitive deps).Testing
go build ./...compiles cleanlygo vet ./...passes (slog's vet checker validates key-value pair correctness)go test ./...all tests passLOG_LEVEL=debugandLOG_LEVEL=errorproduce the expected log output