feat: rewrite logger on log/slog and add a structured logging API - #165
Open
JoshVanL wants to merge 2 commits into
Open
feat: rewrite logger on log/slog and add a structured logging API#165JoshVanL wants to merge 2 commits into
JoshVanL wants to merge 2 commits into
Conversation
kit/logger was a thin wrapper over logrus. Call sites built their
message eagerly with printf verbs, so the output carried no fields that
could be filtered on beyond the fixed schema, and logrus allocated a
fresh map per entry.
Replace the backend with log/slog and add a structured API alongside the
existing one:
```
log := logger.New("dapr.kit")
log.Info("component loaded", "component", name)
log.Error("failed to load component", logger.Err(err))
```
Output is byte-identical to logrus in both text and JSON. The log schema
is documented public API and user log pipelines match on it, so the
encoder reproduces logrus exactly: alphabetical field ordering, the
"warning" level label, omission of an empty message in text but not in
JSON, bare rendering of empty values, and HTML escaping in JSON.
TestGoldenOutput pins all of it against output captured from logrus
before it was removed.
Benchmarked against the previous logrus configuration, same machine,
-count=3:
```
text 1840 ns, 19 allocs, 953 B 810 ns, 3 allocs, 400 B
json 2080 ns, 30 allocs, 1500 B 1070 ns, 4 allocs, 689 B
disabled 21 ns, 1 alloc 20 ns, 1 alloc
```
The emitting path is roughly twice as fast for a sixth of the
allocations. The disabled path is at parity, since both still box
arguments at the call site; LogAttrs is the form that avoids it entirely
at 0 allocations.
On the API:
* Log cannot implement Logger, because the embedded slog methods take a
leading message string andnds. Use
(*Log).Legacy() where a Logger is required.
* logger.FromLogger(Logger) This is the
migration path for code that receives a Logger through a signature
that cannot change, notablnstructor.
* Only the printf methods are marked Deprecated. The Logger interface
and NewLogger are not, becrameter types
for the duration of the migration, and deprecating them would flag
thousands of legitimate us
* Configuration is per logger name and shared between the Logger and the
Log of that name, matching each name
owned its own logrus instance. A component setting its level from
metadata therefore does noole process.
Two existing bugs are fixed
* EnableJSONOutput rebuilt t a second call
silently dropped app_id and any fields added with WithFields.
* Loggers created after Applilt-in defaults
of text output at info level instead of the configured options.
Also converts kit's own call sites to the structured API, drops the
logrus dependency, configurease keys and
reject the reserved schema keys, and fixes a depguard rule that denied
github.com/Sirupsen/logrus, since the
project was renamed, so it had never matched anything.
Signed-off-by: joshvanl <me@joshvanl.dev>
JoshVanL
requested
a balanced review from Copilot
and removed request for
a team
August 13, 2026 17:51
Contributor
There was a problem hiding this comment.
Pull request overview
Replaces the logrus-backed logger with log/slog, adds structured logging, and preserves the existing Dapr log schema.
Changes:
- Adds structured logging, adapters, dynamic configuration, and compatibility encoding.
- Migrates internal call sites to structured attributes.
- Adds tests, benchmarks, lint rules, and removes logrus.
Reviewed changes
Copilot reviewed 26 out of 28 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
.golangci.yml |
Configures slog linting and logrus bans. |
concurrency/closer.go |
Migrates shutdown logging. |
concurrency/dir/dir.go |
Migrates directory operation logging. |
concurrency/dir/switch_unix.go |
Migrates Unix switch logging. |
crypto/spiffe/spiffe.go |
Adds structured SPIFFE logging. |
crypto/spiffe/trustanchors/file/file.go |
Migrates trust-anchor logging. |
errors/errors.go |
Migrates error-detail logging. |
go.mod |
Removes logrus dependency. |
go.sum |
Refreshes dependency checksums. |
jwkscache/cache.go |
Migrates JWKS cache logging. |
logger/attrs.go |
Adds standard structured attributes. |
logger/bench_test.go |
Adds logger benchmarks. |
logger/bridge.go |
Adapts third-party legacy loggers. |
logger/dapr_logger.go |
Reimplements legacy API with slog. |
logger/dapr_logger_test.go |
Updates legacy logger tests. |
logger/golden_capture_test.go |
Pins output compatibility. |
logger/handler.go |
Implements custom schema encoders. |
logger/levels.go |
Maps Dapr and slog levels. |
logger/log.go |
Adds the structured logging API. |
logger/log_test.go |
Tests structured logging behavior. |
logger/logger.go |
Adds shared named configuration. |
logger/nop_logger.go |
Exposes a no-op logger. |
logger/options.go |
Applies persistent runtime configuration. |
logger/options_test.go |
Tests defaults and file output. |
logger/state.go |
Stores concurrent logger state. |
signals/signals.go |
Migrates shutdown signal logging. |
signals/signals_posix.go |
Migrates restart signal logging. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Signed-off-by: joshvanl <me@joshvanl.dev>
This was referenced Aug 13, 2026
|
Afternoon @JoshVanL, I've opened a small PR that adds support for registering additional handlers alongside the primary one. The idea is to make OTLP log export easier to plug in later on. PR: JoshVanL#1 Let me know if this approach makes sense and whether it could be merged into your existing work. |
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.
kit/logger was a thin wrapper over logrus. Call sites built their message eagerly with printf verbs, so the output carried no fields that could be filtered on beyond the fixed schema, and logrus allocated a fresh map per entry.
Replace the backend with log/slog and add a structured API alongside the existing one:
Output is byte-identical to logrus in both text and JSON. The log schema is documented public API and user log pipelines match on it, so the encoder reproduces logrus exactly: alphabetical field ordering, the "warning" level label, omission of an empty message in text but not in JSON, bare rendering of empty values, and HTML escaping in JSON. TestGoldenOutput pins all of it against output captured from logrus before it was removed.
Benchmarked against the previous logrus configuration, same machine, -count=3:
The emitting path is roughly twice as fast for a sixth of the allocations. The disabled path is at parity, since both still box arguments at the call site; LogAttrs is the form that avoids it entirely at 0 allocations.
On the API:
Two existing bugs are fixed
Also converts kit's own call sites to the structured API, drops the logrus dependency, configurease keys and
reject the reserved schema keys, and fixes a depguard rule that denied github.com/Sirupsen/logrus, since the
project was renamed, so it had never matched anything.