Skip to content

Incremental migration to slog - #40120

Merged
getvictor merged 2 commits into
mainfrom
victor/40054-incremental-slog
Feb 19, 2026
Merged

Incremental migration to slog#40120
getvictor merged 2 commits into
mainfrom
victor/40054-incremental-slog

Conversation

@getvictor

@getvictor getvictor commented Feb 19, 2026

Copy link
Copy Markdown
Member

Related issue: Resolves #40054

Checklist for submitter

If some of the following don't apply, delete the relevant line.

  • Changes file added for user-visible changes in changes/, orbit/changes/ or ee/fleetd-chrome/changes.
    • Already added in previous PR

Testing

  • Added/updated automated tests
  • QA'd all new/changed functionality manually

Summary by CodeRabbit

  • Refactor
    • Updated internal logging infrastructure across multiple server components to use standardized logging methods and improved context propagation.

@getvictor

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Feb 19, 2026

Copy link
Copy Markdown
Contributor
✅ Actions performed

Full review triggered.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 continues the incremental migration from go-kit/log to slog across multiple packages in the Fleet server codebase. The migration updates logger types from kitlog.Logger/*logging.Logger to *slog.Logger and replaces go-kit logging calls with slog's context-aware logging methods.

Changes:

  • Migrates logging in pubsub, live_query, errorstore, geoip, and SCIM packages from go-kit/log to slog
  • Updates test files to use slog.New(slog.DiscardHandler) for no-op logging
  • Adds context awareness to logging calls throughout migrated code

Reviewed changes

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

Show a summary per file
File Description
server/service/testing_utils.go Updates calls to errorstore and scim to pass slog logger via SlogLogger() adapter
server/pubsub/testing_utils.go Replaces logging.NewNopLogger() with slog.New(slog.DiscardHandler) in test setup
server/pubsub/redis_query_results.go Migrates redisQueryResults logger field to *slog.Logger and updates all logging calls to use InfoContext/ErrorContext/DebugContext
server/live_query/redis_live_query_test.go Updates test to use slog.New(slog.DiscardHandler) for no-op logging
server/live_query/redis_live_query.go Migrates redisLiveQuery logger to *slog.Logger and updates WarnContext calls (uses context.TODO() where context unavailable)
server/fleet/geoip.go Migrates MaxMindGeoIP logger to *slog.Logger and updates DebugContext calls with proper context
server/errorstore/errors_test.go Updates all test cases to use slog.New(slog.DiscardHandler) instead of kitlog.NewNopLogger()
server/errorstore/errors.go Migrates Handler logger to *slog.Logger and updates ErrorContext calls throughout
ee/server/scim/users_test.go Updates test handler to use slog.New(slog.DiscardHandler) for logger
ee/server/scim/users.go Migrates UserHandler logger to *slog.Logger, extracts context from requests, and updates all logging calls to use slog methods with context
ee/server/scim/scim.go Migrates SCIM middleware and error handlers to use *slog.Logger, updates scimErrorLogger adapter
ee/server/scim/groups.go Migrates GroupHandler logger to *slog.Logger, extracts context from requests, and updates all logging calls to use slog methods with context
cmd/fleet/serve.go Updates initialization code to call SlogLogger() adapter when passing logger to migrated components

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

Comment thread server/live_query/redis_live_query.go
Comment thread server/live_query/redis_live_query.go
Comment thread ee/server/scim/scim.go
Comment thread ee/server/scim/scim.go
@coderabbitai

coderabbitai Bot commented Feb 19, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This pull request migrates the logging backend from go-kit/log to Go's standard library slog across multiple Fleet components. Function signatures are updated to accept *slog.Logger instead of kitlog.Logger or similar types. Logging calls throughout SCIM handlers, error store, geo-IP, live query, and pub/sub components are replaced with slog-based methods like ErrorContext, InfoContext, and WarnContext. Struct fields storing logger instances are updated to store pointers to *slog.Logger. The changes affect both public API signatures and internal implementations across approximately 13 files.

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The PR description is largely incomplete and lacks most required sections from the template. Complete the description by filling out required sections: remove unchecked items or mark completed items with [x], and add details about input validation, endpoint compatibility, automated tests, database migrations, and fleetd compatibility as applicable.
Title check ❓ Inconclusive The title 'Incremental migration to slog' is vague and generic, using non-descriptive terms that don't clearly convey specific changes beyond a migration effort. Consider adding specifics about which components are being migrated (e.g., 'Migrate logging in SCIM, pubsub, and error store to slog').
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR implements a slog migration across multiple components (SCIM, pubsub, errorstore, fleet geoip, live_query) as required by the linked issues.
Out of Scope Changes check ✅ Passed All changes are directly related to migrating from go-kit logging to standard slog, with no unrelated functionality introduced.

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

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch victor/40054-incremental-slog

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (4)
server/live_query/redis_live_query.go (1)

253-253: context.TODO() prevents context-aware log correlation.

collectBatchQueriesForHost doesn't receive a context.Context, so context.TODO() is used here. While context.TODO() is the correct placeholder idiom, downstream logging infrastructure (e.g., trace-ID propagation) won't see the request context. Same applies to line 428 inside the goroutine in loadCache.

Consider threading ctx through collectBatchQueriesForHost and loadCache (the call chain originates from QueriesForHost which could carry a context) in a follow-up refactor.

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

In `@server/live_query/redis_live_query.go` at line 253,
collectBatchQueriesForHost currently uses context.TODO() when calling
r.logger.WarnContext (and loadCache spawns a goroutine that does the same),
which prevents request-scoped trace/log correlation; update the function
signatures to accept a context.Context (add ctx parameter to
collectBatchQueriesForHost and loadCache and propagate it from QueriesForHost),
replace context.TODO() with the passed ctx in r.logger.WarnContext calls, and
ensure the goroutine in loadCache captures and uses that ctx (or a derived
context) so logging and tracing downstream receive the real request context.
cmd/fleet/serve.go (1)

87-89: Duplicate import of github.com/go-kit/log.

Lines 87-88 import the same package under two aliases (log and kitlog). Both resolve to the same type. This is pre-existing and not introduced by this PR, but worth consolidating to a single alias in a future cleanup.

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

In `@cmd/fleet/serve.go` around lines 87 - 89, The file imports the same package
twice as two aliases (`log` and `kitlog`), causing a duplicate import; remove
one of the imports (choose either `log` or `kitlog`) and update any references
to the removed alias (e.g., occurrences of kitlog or log used with functions
like kitlog.NewJSONLogger or level.Error) to use the remaining alias so all
usages reference the single imported symbol.
ee/server/scim/scim.go (1)

377-394: context.TODO() in errorHandler — consider accepting context.

errorHandler is always called from HTTP handler contexts where r.Context() is available (lines 212 and 370), yet it uses context.TODO() for ErrorContext calls. Passing a context.Context parameter would allow proper context propagation for tracing/observability.

Suggested improvement
-func errorHandler(w http.ResponseWriter, logger *slog.Logger, detail string, status int) {
+func errorHandler(w http.ResponseWriter, logger *slog.Logger, ctx context.Context, detail string, status int) {
 	scimErr := scimerrors.ScimError{
 		Status: status,
 		Detail: detail,
 	}
 	raw, err := json.Marshal(scimErr)
 	if err != nil {
-		logger.ErrorContext(context.TODO(), "failed marshaling scim error", "scimError", scimErr, "err", err)
+		logger.ErrorContext(ctx, "failed marshaling scim error", "scimError", scimErr, "err", err)
 		return
 	}
 
 	w.Header().Set("Content-Type", "application/scim+json")
 	w.WriteHeader(scimErr.Status)
 	_, err = w.Write(raw)
 	if err != nil {
-		logger.ErrorContext(context.TODO(), "failed writing response", "err", err)
+		logger.ErrorContext(ctx, "failed writing response", "err", err)
 	}
 }

The callers would need updating too (the closure at line 211 and the call at line 370).

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

In `@ee/server/scim/scim.go` around lines 377 - 394, Change errorHandler to accept
a context.Context parameter and use that context when calling
logger.ErrorContext instead of context.TODO(); update its signature
(errorHandler) and all call sites (the HTTP handler closure that currently calls
errorHandler and the direct call near where scimerrors.ScimError is created) to
pass r.Context() from the incoming *http.Request, ensuring you still set
headers/status and write the marshaled scimErr as before; keep using
scimerrors.ScimError, json.Marshal, and logger.ErrorContext but replace
context.TODO() with the propagated ctx parameter.
ee/server/scim/users.go (1)

593-614: Pre-existing: User email logged at Info/Warn level.

These lines log fleetUser.Email (PII) at Info and Warn levels. While this isn't new to this PR (the slog migration preserves existing logging behavior), it's worth flagging for a future pass to ensure compliance with PII logging policies.

Lines 594, 608, and 614 all include "email", fleetUser.Email in structured log output.

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

In `@ee/server/scim/users.go` around lines 593 - 614, The logs in the SCIM user
deletion flow currently include PII (fleetUser.Email) in calls to
u.logger.InfoContext and u.logger.WarnContext (the "skipping deletion..." log,
the "cannot delete last global admin..." warn, and the "deleting fleet user via
SCIM deletion" info); remove or redact the raw email before logging to avoid
emitting PII. Update the three logging sites that reference "email",
fleetUser.Email to either omit the email key entirely or replace it with a
non-PII token (e.g., a hashed/partial redaction string derived from
fleetUser.Email) so that u.logger.InfoContext / u.logger.WarnContext no longer
receive the plain email value. Ensure the change is applied in the SCIM deletion
flow around the checks for fleetUser.APIOnly / fleetUser.SSOEnabled and the
GlobalRole/CountGlobalAdmins branch.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@cmd/fleet/serve.go`:
- Around line 87-89: The file imports the same package twice as two aliases
(`log` and `kitlog`), causing a duplicate import; remove one of the imports
(choose either `log` or `kitlog`) and update any references to the removed alias
(e.g., occurrences of kitlog or log used with functions like
kitlog.NewJSONLogger or level.Error) to use the remaining alias so all usages
reference the single imported symbol.

In `@ee/server/scim/scim.go`:
- Around line 377-394: Change errorHandler to accept a context.Context parameter
and use that context when calling logger.ErrorContext instead of context.TODO();
update its signature (errorHandler) and all call sites (the HTTP handler closure
that currently calls errorHandler and the direct call near where
scimerrors.ScimError is created) to pass r.Context() from the incoming
*http.Request, ensuring you still set headers/status and write the marshaled
scimErr as before; keep using scimerrors.ScimError, json.Marshal, and
logger.ErrorContext but replace context.TODO() with the propagated ctx
parameter.

In `@ee/server/scim/users.go`:
- Around line 593-614: The logs in the SCIM user deletion flow currently include
PII (fleetUser.Email) in calls to u.logger.InfoContext and u.logger.WarnContext
(the "skipping deletion..." log, the "cannot delete last global admin..." warn,
and the "deleting fleet user via SCIM deletion" info); remove or redact the raw
email before logging to avoid emitting PII. Update the three logging sites that
reference "email", fleetUser.Email to either omit the email key entirely or
replace it with a non-PII token (e.g., a hashed/partial redaction string derived
from fleetUser.Email) so that u.logger.InfoContext / u.logger.WarnContext no
longer receive the plain email value. Ensure the change is applied in the SCIM
deletion flow around the checks for fleetUser.APIOnly / fleetUser.SSOEnabled and
the GlobalRole/CountGlobalAdmins branch.

In `@server/live_query/redis_live_query.go`:
- Line 253: collectBatchQueriesForHost currently uses context.TODO() when
calling r.logger.WarnContext (and loadCache spawns a goroutine that does the
same), which prevents request-scoped trace/log correlation; update the function
signatures to accept a context.Context (add ctx parameter to
collectBatchQueriesForHost and loadCache and propagate it from QueriesForHost),
replace context.TODO() with the passed ctx in r.logger.WarnContext calls, and
ensure the goroutine in loadCache captures and uses that ctx (or a derived
context) so logging and tracing downstream receive the real request context.

@getvictor
getvictor marked this pull request as ready for review February 19, 2026 20:26
@getvictor
getvictor requested a review from a team as a code owner February 19, 2026 20:26
@codecov

codecov Bot commented Feb 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 52.04918% with 117 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.29%. Comparing base (4236363) to head (80d0cf2).
⚠️ Report is 9 commits behind head on main.

Files with missing lines Patch % Lines
ee/server/scim/users.go 60.99% 55 Missing ⚠️
ee/server/scim/groups.go 38.80% 41 Missing ⚠️
cmd/fleet/serve.go 0.00% 5 Missing ⚠️
ee/server/scim/scim.go 54.54% 5 Missing ⚠️
server/pubsub/redis_query_results.go 42.85% 4 Missing ⚠️
server/fleet/geoip.go 0.00% 3 Missing ⚠️
server/errorstore/errors.go 50.00% 2 Missing ⚠️
server/live_query/redis_live_query.go 33.33% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #40120   +/-   ##
=======================================
  Coverage   66.29%   66.29%           
=======================================
  Files        2446     2446           
  Lines      196002   196018   +16     
  Branches     8640     8640           
=======================================
+ Hits       129931   129946   +15     
- Misses      54304    54306    +2     
+ Partials    11767    11766    -1     
Flag Coverage Δ
backend 68.09% <52.04%> (+<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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sgress454 sgress454 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looked at all files and I couldn't detect any issues with my human eyes.

Comment thread ee/server/scim/groups.go
Comment on lines -42 to +41
level.Error(g.logger).Log("msg", "failed to get displayName", "err", err)
g.logger.ErrorContext(r.Context(), "failed to get displayName", "err", err)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FWIW I like the ctx := r.Context() pattern better than calling r.Context() everywhere. I don't think it matters here because these all just return immediately after logging, and we don't update the context anywhere, but if we did (for example, to add a log topic) then we'd want to use the var.

Comment thread ee/server/scim/scim.go
// We do not save unauthenticated error details; we simply log them.
level.Info(logger).Log(
"msg", "unauthenticated request",
logger.InfoContext(r.Context(), "unauthenticated request",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

same comment re: r.Context() vs. a shared ctx var

Comment thread ee/server/scim/scim.go
Comment on lines -386 to +384
level.Error(logger).Log("msg", "failed marshaling scim error", "scimError", scimErr, "err", err)
logger.ErrorContext(context.TODO(), "failed marshaling scim error", "scimError", scimErr, "err", err)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is the goal to add context to every log to enable log traces? Otherwise we could just use logger.Error() here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes. We have a lint rule that explicitly forbids logger.Error()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

slog migration (2)

3 participants