fix(logging): port upstream slog-leveler fixes - #14536
Merged
puertomontt merged 4 commits intoAug 11, 2026
Merged
Conversation
pkg/logging is derived from github.com/shashankram/slog-leveler. Upstream PR kgateway-dev#6 (commit 0752d55) is the only change since we forked; port the parts that apply to us. HTTPLevelHandler mutated levels as it iterated the requested components, so a request naming an unknown component was applied partially. Because Go randomizes map iteration order, the same request returned 200 or 400 nondeterministically: on the 200 path the known component's level was changed despite the request failing, and http.Error fired after w.Write had already committed the status, producing a body with both a success line and an error line. Validate every component up front, then mutate. Also: - Remove the exported GlobalLevel. It was documented as the LevelVar for the default logger but was never stored in componentLeveler and never read outside a test that compared it against its own zero value. - Reset the componentLeveler map between tests instead of only resetting levels, so components no longer leak across cases. - Fix the HTTPLelevelHandler doc typo and document that DeleteLeveler leaves existing loggers working but disconnected from SetLevel/GetLevel. Not ported: upstream replaced init() with an explicit SetDefault(). That model assumes component loggers are not created as package-level vars, which is exactly our convention, so init() stays. Signed-off-by: omar <omar.hammami@solo.io>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR ports key fixes from upstream slog-leveler into kgateway’s pkg/logging, primarily to make HTTPLevelHandler’s component-level updates atomic (validate all requested components before mutating any levels) and to clean up related test and API surface issues.
Changes:
- Fix
HTTPLevelHandlerto validate all requested components up-front to avoid partial updates and nondeterministic success/failure responses. - Remove the exported (but inert)
GlobalLeveland adjust tests accordingly. - Improve test isolation by fully resetting the
componentLevelermap between test cases; update docs/typos.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| pkg/logging/logger.go | Clarifies DeleteLeveler behavior in docs (loggers remain usable but become disconnected from Set/Get). |
| pkg/logging/logger_test.go | Adds resetComponentLeveler() helper and uses it to prevent cross-test pollution. |
| pkg/logging/level.go | Removes GlobalLevel, fixes handler comment typo, and makes HTTPLevelHandler validate components before mutating levels. |
| pkg/logging/level_test.go | Updates expectations for GlobalLevel removal and uses resetComponentLeveler() for stronger test isolation. |
| name = DefaultComponent | ||
| } | ||
| if _, ok := componentLeveler.Load(name); !ok { | ||
| http.Error(w, fmt.Sprintf("logger not found for component: %s", component), http.StatusBadRequest) |
puertomontt
enabled auto-merge
August 7, 2026 15:49
andy-fong
approved these changes
Aug 11, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Aug 11, 2026
…logging-upstream-sync
puertomontt
enabled auto-merge
August 11, 2026 14:30
andy-fong
approved these changes
Aug 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
pkg/loggingis derived from slog-leveler. Upstream PR #6 (0752d55) is the only change since we forked; this ports the parts that apply to us.The bug:
HTTPLevelHandlermutated component levels as it iterated the parsed request, so a request naming an unknown component was applied partially. Because Go randomizes map iteration order, the same request returned 200 or 400 nondeterministically — the same input, eight times:On the 200 path the known component's level is changed despite the request failing, and
http.Errorfires afterw.Writehas already committed the status, so the response carries both a success line and an error line. Note that the bad-level case was already atomic (parsed in an earlier loop); only unknown components leaked. Fixed by validating every requested component up front, then mutating.Also in this PR:
GlobalLevel. It was documented as "theslog.LevelVarfor the default logger" but was never stored incomponentLevelerand never read outside a test that compared it against its own zero value. Upstream deleted it in the same PR. Verified zero references repo-wide.componentLevelermap between tests rather than only resetting levels, so components no longer leak across cases.HTTPLelevelHandlerdoc typo, and document thatDeleteLevelerleaves existing loggers working but disconnected fromSetLevel/GetLevel.Not ported: upstream replaced
init()with an explicitSetDefault()thatmainmust call. That model assumes component loggers are not created as package-level vars, since those run beforemainand would find no registered default to inherit from — which is exactly our convention.init()stays.Change Type
/kind fix
Changelog
Additional Notes
GlobalLevelis an exported symbol, so its removal is technically breaking for anything importingpkg/loggingfrom outside the repo. It was inert, and upstream removed it, but happy to split it out if reviewers would rather keep the bug fix isolated.Validation:
go build -tags e2e ./...clean.go test ./pkg/logging/... -race -shuffle=onand./pkg/kgateway/admin/...(the handler's only consumer) pass.golangci-lintbuild over./pkg/logging/...: 0 issues.level must be left untouched,expected: 0, actual: -4) and passed with the fix; the test was dropped from the final diff.Follow-up, not in this PR:
NewWithOptionscomputesAddSource: opts.AddSource || level.Level() <= slog.LevelDebugonce at construction. Because nearly every logger in the repo is a package-levelvarinitialized beforeSetupLoggingapplies the configured level, that clause resolves tofalsefor all butcontroller-runtimeandklog— so first-party component loggers never emitsourceeven at debug. That clause is a kgateway-local addition; upstream has always used plainopts.AddSource.