Skip to content

Commit c6b21ed

Browse files
authored
Merge pull request #19 from veqryn/with-error
Error slog attribute
2 parents 47ec50a + d4bc074 commit c6b21ed

File tree

6 files changed

+61
-31
lines changed

6 files changed

+61
-31
lines changed

.github/workflows/scorecard.yml

+9-17
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ on:
1010
# To guarantee Maintained check is occasionally updated. See
1111
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
1212
#schedule:
13-
#- cron: '18 16 * * 2'
13+
#- cron: '28 21 * * 1'
1414
push:
1515
branches: [ "main" ]
1616

@@ -26,47 +26,39 @@ jobs:
2626
security-events: write
2727
# Needed to publish results and get a badge (see publish_results below).
2828
id-token: write
29-
# Uncomment the permissions below if installing in a private repository.
30-
# contents: read
31-
# actions: read
3229

3330
steps:
3431
- name: "Checkout code"
35-
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
32+
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
3633
with:
3734
persist-credentials: false
3835

3936
- name: "Run analysis"
40-
uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86 # v2.1.2
37+
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
4138
with:
4239
results_file: results.sarif
4340
results_format: sarif
4441
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
45-
# - you want to enable the Branch-Protection check on a *public* repository, or
46-
# - you are installing Scorecard on a *private* repository
42+
# you want to enable the Branch-Protection check on a *public* repository, or
4743
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat.
4844
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
4945

50-
# Public repositories:
51-
# - Publish results to OpenSSF REST API for easy access by consumers
52-
# - Allows the repository to include the Scorecard badge.
53-
# - See https://github.com/ossf/scorecard-action#publishing-results.
54-
# For private repositories:
55-
# - `publish_results` will always be set to `false`, regardless
56-
# of the value entered here.
46+
# - Publish results to OpenSSF REST API for easy access by consumers
47+
# - Allows the repository to include the Scorecard badge.
48+
# - See https://github.com/ossf/scorecard-action#publishing-results.
5749
publish_results: true
5850

5951
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
6052
# format to the repository Actions tab.
6153
- name: "Upload artifact"
62-
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8 # v3.1.0
54+
uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1
6355
with:
6456
name: SARIF file
6557
path: results.sarif
6658
retention-days: 5
6759

6860
# Upload the results to GitHub's code scanning dashboard.
6961
- name: "Upload to code-scanning"
70-
uses: github/codeql-action/upload-sarif@17573ee1cc1b9d061760f3a006fc4aac4f944fd5 # v2.2.4
62+
uses: github/codeql-action/upload-sarif@8a470fddafa5cbb6266ee11b37ef4d8aae19c571 # v3.24.6
7163
with:
7264
sarif_file: results.sarif

README.md

+11-4
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ down the stack and with any libraries that use either slog-context or logr.
5151
### Other Great SLOG Utilities
5252
- [slogctx](https://github.com/veqryn/slog-context): Add attributes to context and have them automatically added to all log lines. Work with a logger stored in context.
5353
- [slogotel](https://github.com/veqryn/slog-context/tree/main/otel): Automatically extract and add [OpenTelemetry](https://opentelemetry.io/) TraceID's to all log lines.
54-
- [slogdedup](https://github.com/veqryn/slog-dedup): Middleware that deduplicates and sorts attributes. Particularly useful for JSON logging.
54+
- [slogdedup](https://github.com/veqryn/slog-dedup): Middleware that deduplicates and sorts attributes. Particularly useful for JSON logging. Format logs for aggregators (Graylog, GCP/Stackdriver, etc).
5555
- [slogbugsnag](https://github.com/veqryn/slog-bugsnag): Middleware that pipes Errors to [Bugsnag](https://www.bugsnag.com/).
56+
- [slogjson](https://github.com/veqryn/slog-json): Formatter that uses the [JSON v2](https://github.com/golang/go/discussions/63397) [library](https://github.com/go-json-experiment/json), with optional single-line pretty-printing.
5657

5758
## Install
5859

@@ -73,6 +74,7 @@ package main
7374

7475
import (
7576
"context"
77+
"errors"
7678
"log/slog"
7779
"os"
7880

@@ -96,7 +98,7 @@ import (
9698
// logger and its attributes will propagate with it, adding these to any log
9799
// lines using that context.
98100
func main() {
99-
h := slog.NewJSONHandler(os.Stdout, nil)
101+
h := slogctx.NewHandler(slog.NewJSONHandler(os.Stdout, nil), nil)
100102
slog.SetDefault(slog.New(h))
101103

102104
// Store the logger inside the context:
@@ -123,17 +125,22 @@ func main() {
123125
// and can take a mix of slog.Attr and key-value pairs.
124126
ctx = slogctx.With(ctx, slog.String("subKey", "subValue"), slog.Bool("someBool", true))
125127

128+
err := errors.New("an error")
129+
126130
// Access the logger in the context directly with handy wrappers for Debug/Info/Warn/Error/Log/LogAttrs:
127-
slogctx.Info(ctx, "main message", "mainKey", "mainValue")
131+
slogctx.Error(ctx, "main message",
132+
slogctx.Err(err),
133+
slog.String("mainKey", "mainValue"))
128134
/*
129135
{
130136
"time":"2023-11-14T00:53:46.363072-07:00",
131-
"level":"INFO",
137+
"level":"ERROR",
132138
"msg":"main message",
133139
"rootKey":"rootValue",
134140
"someGroup":{
135141
"subKey":"subValue",
136142
"someBool":true,
143+
"err":"an error",
137144
"mainKey":"mainValue"
138145
}
139146
}

ctx_test.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package slogctx
33
import (
44
"bytes"
55
"context"
6+
"errors"
67
"log/slog"
78
"testing"
89
)
@@ -80,8 +81,8 @@ func TestCtx(t *testing.T) {
8081
}
8182

8283
buf.Reset()
83-
Error(ctx, "main message", "main1", "arg1", "main1", "arg2")
84-
expectedError := `{"time":"2023-09-29T13:00:59Z","level":"ERROR","msg":"main message","with1":"arg1","with1":"arg2","with2":"arg1","with2":"arg2","group1":{"with4":"arg1","with4":"arg2","with5":"arg1","with5":"arg2","main1":"arg1","main1":"arg2"}}
84+
Error(ctx, "main message", "main1", "arg1", "main1", "arg2", Err(errors.New("an error")))
85+
expectedError := `{"time":"2023-09-29T13:00:59Z","level":"ERROR","msg":"main message","with1":"arg1","with1":"arg2","with2":"arg1","with2":"arg2","group1":{"with4":"arg1","with4":"arg2","with5":"arg1","with5":"arg2","main1":"arg1","main1":"arg2","err":"an error"}}
8586
`
8687
if buf.String() != expectedError {
8788
t.Errorf("Expected:\n%s\nGot:\n%s\n", expectedError, buf.String())

examples/logger-in-ctx/logger-in-ctx-main.go

+9-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"context"
5+
"errors"
56
"log/slog"
67
"os"
78

@@ -25,7 +26,7 @@ import (
2526
// logger and its attributes will propagate with it, adding these to any log
2627
// lines using that context.
2728
func main() {
28-
h := slog.NewJSONHandler(os.Stdout, nil)
29+
h := slogctx.NewHandler(slog.NewJSONHandler(os.Stdout, nil), nil)
2930
slog.SetDefault(slog.New(h))
3031

3132
// Store the logger inside the context:
@@ -52,17 +53,22 @@ func main() {
5253
// and can take a mix of slog.Attr and key-value pairs.
5354
ctx = slogctx.With(ctx, slog.String("subKey", "subValue"), slog.Bool("someBool", true))
5455

56+
err := errors.New("an error")
57+
5558
// Access the logger in the context directly with handy wrappers for Debug/Info/Warn/Error/Log/LogAttrs:
56-
slogctx.Info(ctx, "main message", "mainKey", "mainValue")
59+
slogctx.Error(ctx, "main message",
60+
slogctx.Err(err),
61+
slog.String("mainKey", "mainValue"))
5762
/*
5863
{
5964
"time":"2023-11-14T00:53:46.363072-07:00",
60-
"level":"INFO",
65+
"level":"ERROR",
6166
"msg":"main message",
6267
"rootKey":"rootValue",
6368
"someGroup":{
6469
"subKey":"subValue",
6570
"someBool":true,
71+
"err":"an error",
6672
"mainKey":"mainValue"
6773
}
6874
}

examples_test.go

+19-5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package slogctx_test
22

33
import (
44
"context"
5+
"errors"
56
"log/slog"
67
"os"
78

@@ -56,7 +57,7 @@ func ExampleNewHandler() {
5657
// Use the logger like normal; add attributes, create groups, pass it around:
5758
log := slog.With("rootKey", "rootValue")
5859
log = log.WithGroup("someGroup")
59-
log = log.With("subKey", "subValue8")
60+
log = log.With("subKey", "subValue")
6061

6162
// The prepended/appended attributes end up in all log lines that use that context
6263
log.InfoContext(ctx, "main message", "mainKey", "mainValue")
@@ -94,7 +95,7 @@ func ExampleNewCtx() {
9495
// logger and its attributes will propagate with it, adding these to any log
9596
// lines using that context.
9697

97-
h := slog.NewJSONHandler(os.Stdout, nil)
98+
h := slogctx.NewHandler(slog.NewJSONHandler(os.Stdout, nil), nil)
9899
slog.SetDefault(slog.New(h))
99100

100101
// Store the logger inside the context:
@@ -103,6 +104,13 @@ func ExampleNewCtx() {
103104
// Get the logger back out again at any time, for manual usage:
104105
log := slogctx.FromCtx(ctx)
105106
log.Warn("warning")
107+
/*
108+
{
109+
"time":"2023-11-14T00:53:46.361201-07:00",
110+
"level":"INFO",
111+
"msg":"warning"
112+
}
113+
*/
106114

107115
// Add attributes directly to the logger in the context:
108116
ctx = slogctx.With(ctx, "rootKey", "rootValue")
@@ -112,18 +120,24 @@ func ExampleNewCtx() {
112120

113121
// With and wrapper methods have the same args signature as slog methods,
114122
// and can take a mix of slog.Attr and key-value pairs.
115-
ctx = slogctx.With(ctx, slog.String("subKey", "subValue"))
123+
ctx = slogctx.With(ctx, slog.String("subKey", "subValue"), slog.Bool("someBool", true))
124+
125+
err := errors.New("an error")
116126

117127
// Access the logger in the context directly with handy wrappers for Debug/Info/Warn/Error/Log/LogAttrs:
118-
slogctx.Info(ctx, "main message", "mainKey", "mainValue")
128+
slogctx.Error(ctx, "main message",
129+
slogctx.Err(err),
130+
slog.String("mainKey", "mainValue"))
119131
/*
120132
{
121133
"time":"2023-11-14T00:53:46.363072-07:00",
122-
"level":"INFO",
134+
"level":"ERROR",
123135
"msg":"main message",
124136
"rootKey":"rootValue",
125137
"someGroup":{
126138
"subKey":"subValue",
139+
"someBool":true,
140+
"err":"an error",
127141
"mainKey":"mainValue"
128142
}
129143
}

wrappers.go

+10
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ import (
77
"time"
88
)
99

10+
// ErrKey is the key used by handlers for an error
11+
// when the log method is called. The associated Value is an error.
12+
const ErrKey = "err" // TODO: consider making a var to allow changes before.
13+
14+
// Err is a convenience method that creates a [slog.Attr] out of an error.
15+
// It uses a consistent key: [ErrKey]
16+
func Err(err error) slog.Attr {
17+
return slog.Any(ErrKey, err)
18+
}
19+
1020
// With calls With on the logger stored in the context,
1121
// or if there isn't any, on the default logger.
1222
// This new logger is stored in a child context and the new context is returned.

0 commit comments

Comments
 (0)