Bring main's fixes into next (closes #16)
Merges main into next as a two-parent merge, so main becomes an ancestor of next and the later merge of next into main does not conflict. This brings in golangci-lint v2.12.2 with .golangci.yml, and the fix that makes every handler emit slog attributes. README.md and TODO.md conflicted. README.md keeps main's Attribute output section, followed by next's Entrypoints section. TODO.md keeps the completed steps from both sides, newest first. The other files merged cleanly: the Makefile is still next's script/ shims, and the Dockerfile has main's v2.12.2 lint image. Model: opus-5-5
This commit is contained in:
@@ -18,6 +18,13 @@ Released v1.0.0 2024-06-14. Works as intended. No known bugs.
|
||||
- if output is a tty, outputs pretty color logs
|
||||
- if output is not a tty, outputs json
|
||||
- supports delivering each log message via a webhook
|
||||
- emits every `slog` attribute: those passed to a log call, those
|
||||
accumulated with `WithAttrs`, and those qualified by `WithGroup`.
|
||||
`slog.Group` values nest, and `slog.LogValuer` values are resolved. In
|
||||
json output attributes are object fields (groups become nested objects);
|
||||
in console output they are appended as `key=value` pairs, with grouped
|
||||
keys written as `group.key=value`. See
|
||||
[Attribute output](#attribute-output) for the details worth knowing
|
||||
|
||||
## Planned Features
|
||||
|
||||
@@ -60,6 +67,43 @@ func main() {
|
||||
}
|
||||
```
|
||||
|
||||
## Attribute output
|
||||
|
||||
Attributes reach every handler: the ones passed to the log call, the ones
|
||||
accumulated with `WithAttrs`, and the ones qualified by the groups open at
|
||||
the time they were attached. `slog.Group` values nest, and
|
||||
`slog.LogValuer` values are resolved to the value they stand for. A few
|
||||
behaviours are worth knowing before you rely on them.
|
||||
|
||||
**Your values are never modified.** Whatever you log is read and rendered,
|
||||
never written to. A map or a slice you pass to `slog.Any` comes back from
|
||||
the logger exactly as you handed it over, even when a group later uses the
|
||||
same key.
|
||||
|
||||
**Durations are nanoseconds in json, and readable on the console.** The
|
||||
json and webhook payloads emit a `slog.Duration` as a number of
|
||||
nanoseconds, matching `slog.NewJSONHandler`, so a consumer can compare and
|
||||
aggregate the field without parsing it. The console line emits the same
|
||||
duration as `3s`, matching `slog.NewTextHandler`, because a person reads
|
||||
it.
|
||||
|
||||
**The json payload is an object, with the consequences an object has.**
|
||||
The record's own fields are named `Time`, `Level`, `Message` and `PC`, and
|
||||
they own those names: an attribute keyed after one of them is dropped from
|
||||
the json and webhook output. A key logged more than once keeps its last
|
||||
value there for the same reason, with one exception: when both are
|
||||
`slog.Group` values sharing a key, the two groups are merged into one
|
||||
object holding the members of both, rather than the second replacing the
|
||||
first. Neither the collision nor the merge applies to the console output,
|
||||
which is a line of text: every pair appears, in order. If you need a field
|
||||
called `message`, pick a key that does not collide - the collision is
|
||||
silent.
|
||||
|
||||
**Empty things follow the `slog.Handler` contract.** An empty `Attr` is
|
||||
ignored, an empty group is elided along with its key, a group with an
|
||||
empty key is inlined into its parent, and `WithGroup("")` returns the
|
||||
handler unchanged.
|
||||
|
||||
## Entrypoints
|
||||
|
||||
This repository adheres to the
|
||||
|
||||
Reference in New Issue
Block a user