From 68327e2dc4b2ed60148b66389739eb906702b4ec Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Mon, 8 May 2023 21:47:38 -0500 Subject: [PATCH 01/24] Switch human logger from JSON to logfmt (#170) --- .github/workflows/ci.yml | 41 +-- ci/fmt.mk | 9 +- ci/image/Dockerfile | 14 - ci/lint.mk | 2 +- ci/test.mk | 2 +- example_test.go | 27 +- go.mod | 24 +- go.sum | 42 +-- internal/entryhuman/entry.go | 211 ++++++++------- internal/entryhuman/entry_test.go | 242 ++++++++++++------ internal/entryhuman/json.go | 42 --- internal/entryhuman/testdata/bytes.golden | 1 + internal/entryhuman/testdata/funky.golden | 1 + .../entryhuman/testdata/multilineField.golden | 3 + .../testdata/multilineMessage.golden | 3 + internal/entryhuman/testdata/named.golden | 1 + internal/entryhuman/testdata/object.golden | 1 + .../entryhuman/testdata/simpleNoFields.golden | 1 + internal/entryhuman/testdata/spacey.golden | 1 + map_test.go | 6 +- s_test.go | 2 +- sloggers/sloghuman/sloghuman.go | 40 ++- sloggers/sloghuman/sloghuman_test.go | 19 +- sloggers/slogtest/assert/assert.go | 1 - sloggers/slogtest/assert/assert_test.go | 3 +- sloggers/slogtest/t.go | 4 +- 26 files changed, 408 insertions(+), 335 deletions(-) delete mode 100644 ci/image/Dockerfile delete mode 100644 internal/entryhuman/json.go create mode 100644 internal/entryhuman/testdata/bytes.golden create mode 100644 internal/entryhuman/testdata/funky.golden create mode 100644 internal/entryhuman/testdata/multilineField.golden create mode 100644 internal/entryhuman/testdata/multilineMessage.golden create mode 100644 internal/entryhuman/testdata/named.golden create mode 100644 internal/entryhuman/testdata/object.golden create mode 100644 internal/entryhuman/testdata/simpleNoFields.golden create mode 100644 internal/entryhuman/testdata/spacey.golden diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c3d75a3..4a212ec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,38 +12,25 @@ on: workflow_dispatch: jobs: - fmt: - runs-on: ubuntu-20.04 + go: + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - - name: make fmt - uses: ./ci/image + - uses: actions/checkout@v3 + - name: Cache npm + uses: actions/cache@v3 with: - args: make fmt - - lint: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 - - - name: make lint - uses: ./ci/image + path: ~/.npm + key: "npm-cache" + - uses: actions/setup-go@v4 with: - args: make lint - - test: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 - - - name: make test - uses: ./ci/image - with: - args: make test + go-version: "1.20" + cache-dependency-path: go.sum + - name: "make" + run: | + git config --global --add safe.directory /github/workspace + make -O -j fmt lint test env: COVERALLS_TOKEN: ${{ secrets.github_token }} - - name: Upload coverage.html uses: actions/upload-artifact@v2 with: diff --git a/ci/fmt.mk b/ci/fmt.mk index 026cc36..7f74874 100644 --- a/ci/fmt.mk +++ b/ci/fmt.mk @@ -1,4 +1,4 @@ -fmt: modtidy gofmt goimports prettier +fmt: modtidy gofmt prettier ifdef CI if [[ $$(git ls-files --other --modified --exclude-standard) != "" ]]; then echo "Files need generation or are formatted incorrectly:" @@ -13,13 +13,10 @@ modtidy: gen go mod tidy gofmt: gen - gofmt -w -s . - -goimports: gen - goimports -w "-local=$$(go list -m)" . + go run mvdan.cc/gofumpt@latest -w . prettier: - prettier --write --print-width=120 --no-semi --trailing-comma=all --loglevel=warn $$(git ls-files "*.yml") + npx prettier --write --print-width=120 --no-semi --trailing-comma=all --loglevel=warn $$(git ls-files "*.yml") gen: go generate ./... diff --git a/ci/image/Dockerfile b/ci/image/Dockerfile deleted file mode 100644 index 2c6988e..0000000 --- a/ci/image/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -FROM golang:1 - -RUN apt-get update && \ - apt-get install -y npm - -ENV GOFLAGS="-mod=readonly" -ENV PAGER=cat -ENV CI=true -ENV MAKEFLAGS="--jobs=8 --output-sync=target" - -RUN npm install -g prettier -RUN go install golang.org/x/tools/cmd/goimports@latest -RUN go install golang.org/x/lint/golint@latest -RUN go install github.com/mattn/goveralls@latest diff --git a/ci/lint.mk b/ci/lint.mk index fbf42d2..36da85b 100644 --- a/ci/lint.mk +++ b/ci/lint.mk @@ -4,4 +4,4 @@ govet: go vet ./... golint: - golint -set_exit_status ./... + go run github.com/golangci/golangci-lint/cmd/golangci-lint@latest run . diff --git a/ci/test.mk b/ci/test.mk index 2615c51..35bfd05 100644 --- a/ci/test.mk +++ b/ci/test.mk @@ -15,7 +15,7 @@ coveralls: gotest export CI_PULL_REQUEST="$$(jq .number "$$GITHUB_EVENT_PATH")" BUILD_NUMBER="$$BUILD_NUMBER-PR-$$CI_PULL_REQUEST" fi - goveralls -coverprofile=ci/out/coverage.prof -service=github + go run github.com/mattn/goveralls@latest -coverprofile=ci/out/coverage.prof -service=github gotest: go test -covermode=count -coverprofile=ci/out/coverage.prof -coverpkg=./... $${GOTESTFLAGS-} ./... diff --git a/example_test.go b/example_test.go index 2853ff7..95131ee 100644 --- a/example_test.go +++ b/example_test.go @@ -8,7 +8,6 @@ import ( "testing" "time" - "go.opencensus.io/trace" "golang.org/x/xerrors" "cdr.dev/slog" @@ -72,23 +71,13 @@ func Example_testing() { slog.F("field_name", "something or the other"), ) - // t.go:55: 2019-12-05 21:20:31.218 [INFO] my message here {"field_name": "something or the other"} -} - -func Example_tracing() { - log := slog.Make(sloghuman.Sink(os.Stdout)) - - ctx, _ := trace.StartSpan(context.Background(), "spanName") - - log.Info(ctx, "my msg", slog.F("hello", "hi")) - - // 2019-12-09 21:59:48.110 [INFO] my msg {"trace": "f143d018d00de835688453d8dc55c9fd", "span": "f214167bf550afc3", "hello": "hi"} + // t.go:55: 2019-12-05 21:20:31.218 [INFO] my message here field_name="something or the other" } func Example_multiple() { l := slog.Make(sloghuman.Sink(os.Stdout)) - f, err := os.OpenFile("stackdriver", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0644) + f, err := os.OpenFile("stackdriver", os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0o644) if err != nil { l.Fatal(context.Background(), "failed to open stackdriver log file", slog.Error(err)) } @@ -97,7 +86,7 @@ func Example_multiple() { l.Info(context.Background(), "log to stdout and stackdriver") - // 2019-12-07 20:59:55.790 [INFO] log to stdout and stackdriver + // 2019-12-07 20:59:55.790 [INFO] log to stdout and stackdriver } func ExampleWith() { @@ -106,7 +95,7 @@ func ExampleWith() { l := slog.Make(sloghuman.Sink(os.Stdout)) l.Info(ctx, "msg") - // 2019-12-07 20:54:23.986 [INFO] msg {"field": 1} + // 2019-12-07 20:54:23.986 [INFO] msg field=1} } func ExampleStdlib() { @@ -115,7 +104,7 @@ func ExampleStdlib() { l.Print("msg") - // 2019-12-07 20:54:23.986 [INFO] (stdlib) msg {"field": 1} + // 2019-12-07 20:54:23.986 [INFO] (stdlib) msg field=1 } func ExampleLogger_Named() { @@ -125,7 +114,7 @@ func ExampleLogger_Named() { l = l.Named("http") l.Info(ctx, "received request", slog.F("remote address", net.IPv4(127, 0, 0, 1))) - // 2019-12-07 21:20:56.974 [INFO] (http) received request {"remote address": "127.0.0.1"} + // 2019-12-07 21:20:56.974 [INFO] (http) received request remote_address=127.0.0.1} } func ExampleLogger_Leveled() { @@ -139,6 +128,6 @@ func ExampleLogger_Leveled() { l.Debug(ctx, "testing2") - // 2019-12-07 21:26:20.945 [INFO] received request - // 2019-12-07 21:26:20.945 [DEBUG] testing2 + // 2019-12-07 21:26:20.945 [INFO] received request + // 2019-12-07 21:26:20.945 [DEBU] testing2 } diff --git a/go.mod b/go.mod index ac067d3..c1fd46d 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,31 @@ module cdr.dev/slog -go 1.13 +go 1.20 require ( cloud.google.com/go v0.26.0 - github.com/alecthomas/chroma v0.10.0 - github.com/fatih/color v1.13.0 + github.com/charmbracelet/lipgloss v0.7.1 github.com/google/go-cmp v0.5.3 + github.com/muesli/termenv v0.15.1 go.opencensus.io v0.24.0 - go.uber.org/goleak v1.2.1 // indirect + go.uber.org/goleak v1.2.1 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 ) + +require ( + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect + github.com/golang/protobuf v1.4.3 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/muesli/reflow v0.3.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect + golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/text v0.3.3 // indirect + google.golang.org/grpc v1.33.2 // indirect + google.golang.org/protobuf v1.25.0 // indirect +) diff --git a/go.sum b/go.sum index 7de8934..4b64d35 100644 --- a/go.sum +++ b/go.sum @@ -1,22 +1,20 @@ cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= -github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/charmbracelet/lipgloss v0.7.1 h1:17WMwi7N1b1rVWOjMT+rCh7sQkvDU75B2hbZpc5Kc1E= +github.com/charmbracelet/lipgloss v0.7.1/go.mod h1:yG0k3giv8Qj8edTCbbg6AlQ5e8KNWpFujkNawKNhE2c= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= -github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -39,21 +37,26 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= +github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= +github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs= +github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= @@ -83,11 +86,10 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -121,9 +123,7 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/entryhuman/entry.go b/internal/entryhuman/entry.go index 4e741c9..6c8406d 100644 --- a/internal/entryhuman/entry.go +++ b/internal/entryhuman/entry.go @@ -8,13 +8,14 @@ import ( "fmt" "io" "os" - "path/filepath" - "runtime/debug" + "reflect" "strconv" "strings" "time" + "unicode" - "github.com/fatih/color" + "github.com/charmbracelet/lipgloss" + "github.com/muesli/termenv" "go.opencensus.io/trace" "golang.org/x/crypto/ssh/terminal" "golang.org/x/xerrors" @@ -34,15 +35,49 @@ func StripTimestamp(ent string) (time.Time, string, error) { // TimeFormat is a simplified RFC3339 format. const TimeFormat = "2006-01-02 15:04:05.000" -func c(w io.Writer, attrs ...color.Attribute) *color.Color { - c := color.New(attrs...) - c.DisableColor() +var ( + renderer = lipgloss.NewRenderer(os.Stdout, termenv.WithUnsafe()) + + loggerNameStyle = renderer.NewStyle().Foreground(lipgloss.Color("#A47DFF")) + timeStyle = renderer.NewStyle().Foreground(lipgloss.Color("#606366")) +) + +func render(w io.Writer, st lipgloss.Style, s string) string { if shouldColor(w) { - c.EnableColor() + ss := st.Render(s) + return ss + } + return s +} + +func reset(w io.Writer, termW io.Writer) { + if shouldColor(termW) { + fmt.Fprintf(w, termenv.CSI+termenv.ResetSeq+"m") + } +} + +func formatValue(v interface{}) string { + typ := reflect.TypeOf(v) + switch typ.Kind() { + case reflect.Struct, reflect.Map: + byt, err := json.Marshal(v) + if err != nil { + panic(err) + } + return string(byt) + case reflect.Slice: + // Byte slices are optimistically readable. + if typ.Elem().Kind() == reflect.Uint8 { + return fmt.Sprintf("%q", v) + } + fallthrough + default: + return quote(fmt.Sprintf("%+v", v)) } - return c } +const tab = " " + // Fmt returns a human readable format for ent. // // We never return with a trailing newline because Go's testing framework adds one @@ -50,26 +85,31 @@ func c(w io.Writer, attrs ...color.Attribute) *color.Color { // We also do not indent the fields as go's test does that automatically // for extra lines in a log so if we did it here, the fields would be indented // twice in test logs. So the Stderr logger indents all the fields itself. -func Fmt(w io.Writer, ent slog.SinkEntry) string { - ents := c(w, color.Reset).Sprint("") +func Fmt( + buf interface { + io.StringWriter + io.Writer + }, termW io.Writer, ent slog.SinkEntry, +) { + reset(buf, termW) ts := ent.Time.Format(TimeFormat) - ents += ts + " " + buf.WriteString(render(termW, timeStyle, ts+" ")) - level := "[" + ent.Level.String() + "]" - level = c(w, levelColor(ent.Level)).Sprint(level) - ents += fmt.Sprintf("%v\t", level) + level := ent.Level.String() + level = strings.ToLower(level) + if len(level) > 4 { + level = level[:4] + } + level = "[" + level + "]" + buf.WriteString(render(termW, levelStyle(ent.Level), level)) + buf.WriteString(" ") if len(ent.LoggerNames) > 0 { loggerName := "(" + quoteKey(strings.Join(ent.LoggerNames, ".")) + ")" - loggerName = c(w, color.FgMagenta).Sprint(loggerName) - ents += fmt.Sprintf("%v\t", loggerName) + buf.WriteString(render(termW, loggerNameStyle, loggerName)) + buf.WriteString(tab) } - hpath, hfn := humanPathAndFunc(ent.File, ent.Func) - loc := fmt.Sprintf("<%v:%v>\t%v", hpath, ent.Line, hfn) - loc = c(w, color.FgCyan).Sprint(loc) - ents += fmt.Sprintf("%v\t", loc) - var multilineKey string var multilineVal string msg := strings.TrimSpace(ent.Message) @@ -77,9 +117,9 @@ func Fmt(w io.Writer, ent slog.SinkEntry) string { multilineKey = "msg" multilineVal = msg msg = "..." + msg = quote(msg) } - msg = quote(msg) - ents += msg + buf.WriteString(msg) if ent.SpanContext != (trace.SpanContext{}) { ent.Fields = append(slog.M( @@ -111,48 +151,61 @@ func Fmt(w io.Writer, ent slog.SinkEntry) string { multilineVal = s } - if len(ent.Fields) > 0 { - // No error is guaranteed due to slog.Map handling errors itself. - fields, _ := json.MarshalIndent(ent.Fields, "", "") - fields = bytes.ReplaceAll(fields, []byte(",\n"), []byte(", ")) - fields = bytes.ReplaceAll(fields, []byte("\n"), []byte("")) - fields = formatJSON(w, fields) - ents += "\t" + string(fields) + keyStyle := timeStyle + // Help users distinguish logs by keeping some color in the equal signs. + equalsStyle := timeStyle + + for i, f := range ent.Fields { + if i < len(ent.Fields) { + buf.WriteString(tab) + } + buf.WriteString(render(termW, keyStyle, quoteKey(f.Name))) + buf.WriteString(render(termW, equalsStyle, "=")) + valueStr := formatValue(f.Value) + buf.WriteString(valueStr) } if multilineVal != "" { if msg != "..." { - ents += " ..." + buf.WriteString(" ...") } // Proper indentation. lines := strings.Split(multilineVal, "\n") for i, line := range lines[1:] { if line != "" { - lines[i+1] = c(w, color.Reset).Sprint("") + strings.Repeat(" ", len(multilineKey)+4) + line + lines[i+1] = strings.Repeat(" ", len(multilineKey)+2) + line } } multilineVal = strings.Join(lines, "\n") - multilineKey = c(w, color.FgBlue).Sprintf(`"%v"`, multilineKey) - ents += fmt.Sprintf("\n%v: %v", multilineKey, multilineVal) + multilineKey = render(termW, keyStyle, multilineKey) + buf.WriteString("\n") + buf.WriteString(multilineKey) + buf.WriteString("= ") + buf.WriteString(multilineVal) } - - return ents } -func levelColor(level slog.Level) color.Attribute { +var ( + levelDebugStyle = timeStyle.Copy() + levelInfoStyle = renderer.NewStyle().Foreground(lipgloss.Color("#0091FF")) + levelWarnStyle = renderer.NewStyle().Foreground(lipgloss.Color("#FFCF0D")) + levelErrorStyle = renderer.NewStyle().Foreground(lipgloss.Color("#FF5A0D")) +) + +func levelStyle(level slog.Level) lipgloss.Style { switch level { case slog.LevelDebug: - return color.Reset + return levelDebugStyle case slog.LevelInfo: - return color.FgBlue + return levelInfoStyle case slog.LevelWarn: - return color.FgYellow - case slog.LevelError: - return color.FgRed + return levelWarnStyle + case slog.LevelError, slog.LevelFatal, slog.LevelCritical: + return levelErrorStyle default: - return color.FgHiRed + panic("unknown level") } } @@ -182,11 +235,18 @@ func quote(key string) string { return `""` } + var hasSpace bool + for _, r := range key { + if unicode.IsSpace(r) { + hasSpace = true + break + } + } quoted := strconv.Quote(key) // If the key doesn't need to be quoted, don't quote it. // We do not use strconv.CanBackquote because it doesn't // account tabs. - if quoted[1:len(quoted)-1] == key { + if !hasSpace && quoted[1:len(quoted)-1] == key { return key } return quoted @@ -194,66 +254,5 @@ func quote(key string) string { func quoteKey(key string) string { // Replace spaces in the map keys with underscores. - return strings.ReplaceAll(key, " ", "_") -} - -var mainPackagePath string -var mainModulePath string - -func init() { - // Unfortunately does not work for tests yet :( - // See https://github.com/golang/go/issues/33976 - bi, ok := debug.ReadBuildInfo() - if !ok { - return - } - mainPackagePath = bi.Path - mainModulePath = bi.Main.Path -} - -// humanPathAndFunc takes the absolute path to a file and an absolute module path to a -// function in that file and returns the module path to the file. It also returns -// the path to the function stripped of its module prefix. -// -// If the file is in the main Go module then its path is returned -// relative to the main Go module's root. -// -// fn is from https://pkg.go.dev/runtime#Func.Name -func humanPathAndFunc(filename, fn string) (hpath, hfn string) { - // pkgDir is the dir of the pkg. - // e.g. cdr.dev/slog/internal - // base is the package name and the function name separated by a period. - // e.g. entryhuman.humanPathAndFunc - // There can be multiple periods when methods of types are involved. - pkgDir, base := filepath.Split(fn) - s := strings.Split(base, ".") - pkg := s[0] - hfn = strings.Join(s[1:], ".") - - if pkg == "main" { - // This happens with go build main.go - if mainPackagePath == "command-line-arguments" { - // Without a real mainPath, we can't find the path to the file - // relative to the module. So we just return the base. - return filepath.Base(filename), hfn - } - // Go doesn't return the full main path in runtime.Func.Name() - // It just returns the path "main" - // Only runtime.ReadBuildInfo returns it so we have to check and replace. - pkgDir = mainPackagePath - // pkg main isn't reflected on the disk so we should not add it - // into the pkgpath. - pkg = "" - } - - hpath = filepath.Join(pkgDir, pkg, filepath.Base(filename)) - - if mainModulePath != "" { - relhpath, err := filepath.Rel(mainModulePath, hpath) - if err == nil { - hpath = "./" + relhpath - } - } - - return hpath, hfn + return quote(strings.ReplaceAll(key, " ", "_")) } diff --git a/internal/entryhuman/entry_test.go b/internal/entryhuman/entry_test.go index f7fc596..6c62827 100644 --- a/internal/entryhuman/entry_test.go +++ b/internal/entryhuman/entry_test.go @@ -1,12 +1,14 @@ package entryhuman_test import ( - "io/ioutil" + "bytes" + "flag" + "fmt" + "io" + "os" "testing" "time" - "go.opencensus.io/trace" - "cdr.dev/slog" "cdr.dev/slog/internal/assert" "cdr.dev/slog/internal/entryhuman" @@ -14,81 +16,177 @@ import ( var kt = time.Date(2000, time.February, 5, 4, 4, 4, 4, time.UTC) +var updateGoldenFiles = flag.Bool("update-golden-files", false, "update golden files in testdata") + +type testObj struct { + foo int + bar int + dra []byte +} + func TestEntry(t *testing.T) { t.Parallel() - test := func(t *testing.T, in slog.SinkEntry, exp string) { - act := entryhuman.Fmt(ioutil.Discard, in) - assert.Equal(t, "entry", exp, act) + type tcase struct { + name string + ent slog.SinkEntry } - t.Run("basic", func(t *testing.T) { - t.Parallel() - - test(t, slog.SinkEntry{ - Message: "wowowow\tizi", - Time: kt, - Level: slog.LevelDebug, - - File: "myfile", - Line: 100, - Func: "mypkg.ignored", - }, `2000-02-05 04:04:04.000 [DEBUG] ignored "wowowow\tizi"`) - }) - - t.Run("multilineMessage", func(t *testing.T) { - t.Parallel() - - test(t, slog.SinkEntry{ - Message: "line1\nline2", - Level: slog.LevelInfo, - }, `0001-01-01 00:00:00.000 [INFO] <.:0> ... -"msg": line1 - line2`) - }) - - t.Run("multilineField", func(t *testing.T) { - t.Parallel() - - test(t, slog.SinkEntry{ - Message: "msg", - Level: slog.LevelInfo, - Fields: slog.M(slog.F("field", "line1\nline2")), - }, `0001-01-01 00:00:00.000 [INFO] <.:0> msg ... -"field": line1 - line2`) - }) - - t.Run("named", func(t *testing.T) { - t.Parallel() - - test(t, slog.SinkEntry{ - Level: slog.LevelWarn, - LoggerNames: []string{"named", "meow"}, - }, `0001-01-01 00:00:00.000 [WARN] (named.meow) <.:0> ""`) - }) - - t.Run("trace", func(t *testing.T) { - t.Parallel() - - test(t, slog.SinkEntry{ - Level: slog.LevelError, - SpanContext: trace.SpanContext{ - SpanID: trace.SpanID{0, 1, 2, 3, 4, 5, 6, 7}, - TraceID: trace.TraceID{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + ents := []tcase{ + { + "simpleNoFields", + slog.SinkEntry{ + Message: "wowowow\tizi", + Time: kt, + Level: slog.LevelDebug, + + File: "myfile", + Line: 100, + Func: "mypkg.ignored", }, - }, `0001-01-01 00:00:00.000 [ERROR] <.:0> "" {"trace": "000102030405060708090a0b0c0d0e0f", "span": "0001020304050607"}`) - }) - - t.Run("color", func(t *testing.T) { - t.Parallel() + }, + { + "multilineMessage", + slog.SinkEntry{ + Message: "line1\nline2", + Level: slog.LevelInfo, + }, + }, + { + "multilineField", + slog.SinkEntry{ + Message: "msg", + Level: slog.LevelInfo, + Fields: slog.M(slog.F("field", "line1\nline2")), + }, + }, + { + "named", + slog.SinkEntry{ + Level: slog.LevelWarn, + LoggerNames: []string{"named", "meow"}, + }, + }, + { + "funky", + slog.SinkEntry{ + Level: slog.LevelWarn, + Fields: slog.M( + slog.F("funky^%&^&^key", "value"), + slog.F("funky^%&^&^key2", "@#\t \t \n"), + ), + }, + }, + { + "spacey", + slog.SinkEntry{ + Level: slog.LevelWarn, + Fields: slog.M( + slog.F("space in my key", "value in my value"), + ), + }, + }, + { + "bytes", + slog.SinkEntry{ + Level: slog.LevelWarn, + Fields: slog.M( + slog.F("somefile", []byte("blah bla\x01h blah")), + ), + }, + }, + { + "object", + slog.SinkEntry{ + Level: slog.LevelWarn, + Fields: slog.M( + slog.F("obj", slog.M( + slog.F("obj1", testObj{ + foo: 1, + bar: 2, + dra: []byte("blah"), + }), + slog.F("obj2", testObj{ + foo: 3, + bar: 4, + dra: []byte("blah"), + }), + )), + slog.F("map", map[string]string{ + "key1": "value1", + }), + ), + }, + }, + } + if *updateGoldenFiles { + ents, err := os.ReadDir("testdata") + if err != nil { + t.Fatal(err) + } + for _, ent := range ents { + os.Remove("testdata/" + ent.Name()) + } + } - act := entryhuman.Fmt(entryhuman.ForceColorWriter, slog.SinkEntry{ - Level: slog.LevelCritical, - Fields: slog.M( - slog.F("hey", "hi"), - ), + for _, tc := range ents { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + goldenPath := fmt.Sprintf("testdata/%s.golden", tc.name) + + var gotBuf bytes.Buffer + entryhuman.Fmt(&gotBuf, io.Discard, tc.ent) + + if *updateGoldenFiles { + err := os.WriteFile(goldenPath, gotBuf.Bytes(), 0o644) + if err != nil { + t.Fatal(err) + } + return + } + + wantByt, err := os.ReadFile(goldenPath) + if err != nil { + t.Fatal(err) + } + + assert.Equal(t, "entry matches", string(wantByt), gotBuf.String()) }) - assert.Equal(t, "entry", "\x1b[0m\x1b[0m0001-01-01 00:00:00.000 \x1b[91m[CRITICAL]\x1b[0m\t\x1b[36m<.:0> \x1b[0m\t\"\"\t{\x1b[34m\"hey\"\x1b[0m: \x1b[32m\"hi\"\x1b[0m}", act) - }) + } +} + +func BenchmarkFmt(b *testing.B) { + bench := func(b *testing.B, color bool) { + nfs := []int{1, 4, 16} + for _, nf := range nfs { + name := fmt.Sprintf("nf=%v", nf) + if color { + name = "Colored-" + name + } + b.Run(name, func(b *testing.B) { + fs := make([]slog.Field, nf) + for i := 0; i < nf; i++ { + fs[i] = slog.F("key", "value") + } + se := slog.SinkEntry{ + Level: slog.LevelCritical, + Fields: slog.M( + fs..., + ), + } + w := io.Discard + if color { + w = entryhuman.ForceColorWriter + } + b.ResetTimer() + b.ReportAllocs() + for i := 0; i < b.N; i++ { + entryhuman.Fmt(bytes.NewBuffer(nil), w, se) + } + }) + } + } + bench(b, true) + bench(b, false) } diff --git a/internal/entryhuman/json.go b/internal/entryhuman/json.go deleted file mode 100644 index 25f65f6..0000000 --- a/internal/entryhuman/json.go +++ /dev/null @@ -1,42 +0,0 @@ -package entryhuman - -import ( - "bytes" - "io" - - "github.com/alecthomas/chroma" - "github.com/alecthomas/chroma/formatters" - jlexers "github.com/alecthomas/chroma/lexers/j" -) - -// Adapted from https://github.com/alecthomas/chroma/blob/2f5349aa18927368dbec6f8c11608bf61c38b2dd/styles/bw.go#L7 -// https://github.com/alecthomas/chroma/blob/2f5349aa18927368dbec6f8c11608bf61c38b2dd/formatters/tty_indexed.go -// https://github.com/alecthomas/chroma/blob/2f5349aa18927368dbec6f8c11608bf61c38b2dd/lexers/j/json.go -var style = chroma.MustNewStyle("slog", chroma.StyleEntries{ - // Magenta. - chroma.Keyword: "#7f007f", - // Magenta. - chroma.Number: "#7f007f", - // Magenta. - chroma.Name: "#00007f", - // Green. - chroma.String: "#007f00", -}) - -var jsonLexer = chroma.Coalesce(jlexers.JSON) - -func formatJSON(w io.Writer, buf []byte) []byte { - if !shouldColor(w) { - return buf - } - - highlighted, _ := colorizeJSON(buf) - return highlighted -} - -func colorizeJSON(buf []byte) ([]byte, error) { - it, _ := jsonLexer.Tokenise(nil, string(buf)) - b := &bytes.Buffer{} - formatters.TTY8.Format(b, style, it) - return b.Bytes(), nil -} diff --git a/internal/entryhuman/testdata/bytes.golden b/internal/entryhuman/testdata/bytes.golden new file mode 100644 index 0000000..e4c5490 --- /dev/null +++ b/internal/entryhuman/testdata/bytes.golden @@ -0,0 +1 @@ +0001-01-01 00:00:00.000 [warn] somefile="blah bla\x01h blah" \ No newline at end of file diff --git a/internal/entryhuman/testdata/funky.golden b/internal/entryhuman/testdata/funky.golden new file mode 100644 index 0000000..fc6a460 --- /dev/null +++ b/internal/entryhuman/testdata/funky.golden @@ -0,0 +1 @@ +0001-01-01 00:00:00.000 [warn] funky^%&^&^key=value funky^%&^&^key2="@#\t \t \n" \ No newline at end of file diff --git a/internal/entryhuman/testdata/multilineField.golden b/internal/entryhuman/testdata/multilineField.golden new file mode 100644 index 0000000..a2777d8 --- /dev/null +++ b/internal/entryhuman/testdata/multilineField.golden @@ -0,0 +1,3 @@ +0001-01-01 00:00:00.000 [info] msg ... +field= line1 + line2 \ No newline at end of file diff --git a/internal/entryhuman/testdata/multilineMessage.golden b/internal/entryhuman/testdata/multilineMessage.golden new file mode 100644 index 0000000..233fda6 --- /dev/null +++ b/internal/entryhuman/testdata/multilineMessage.golden @@ -0,0 +1,3 @@ +0001-01-01 00:00:00.000 [info] ... +msg= line1 + line2 \ No newline at end of file diff --git a/internal/entryhuman/testdata/named.golden b/internal/entryhuman/testdata/named.golden new file mode 100644 index 0000000..09efb6e --- /dev/null +++ b/internal/entryhuman/testdata/named.golden @@ -0,0 +1 @@ +0001-01-01 00:00:00.000 [warn] (named.meow) \ No newline at end of file diff --git a/internal/entryhuman/testdata/object.golden b/internal/entryhuman/testdata/object.golden new file mode 100644 index 0000000..855cb06 --- /dev/null +++ b/internal/entryhuman/testdata/object.golden @@ -0,0 +1 @@ +0001-01-01 00:00:00.000 [warn] obj="[{Name:obj1 Value:{foo:1 bar:2 dra:[98 108 97 104]}} {Name:obj2 Value:{foo:3 bar:4 dra:[98 108 97 104]}}]" map={"key1":"value1"} \ No newline at end of file diff --git a/internal/entryhuman/testdata/simpleNoFields.golden b/internal/entryhuman/testdata/simpleNoFields.golden new file mode 100644 index 0000000..db46f6a --- /dev/null +++ b/internal/entryhuman/testdata/simpleNoFields.golden @@ -0,0 +1 @@ +2000-02-05 04:04:04.000 [debu] wowowow izi \ No newline at end of file diff --git a/internal/entryhuman/testdata/spacey.golden b/internal/entryhuman/testdata/spacey.golden new file mode 100644 index 0000000..7135d8c --- /dev/null +++ b/internal/entryhuman/testdata/spacey.golden @@ -0,0 +1 @@ +0001-01-01 00:00:00.000 [warn] space_in_my_key="value in my value" \ No newline at end of file diff --git a/map_test.go b/map_test.go index e15a6ee..fce13b5 100644 --- a/map_test.go +++ b/map_test.go @@ -187,7 +187,7 @@ func TestMap(t *testing.T) { t.Parallel() test(t, slog.M( - slog.F("val", time.Date(2000, 02, 05, 4, 4, 4, 0, time.UTC)), + slog.F("val", time.Date(2000, 0o2, 0o5, 4, 4, 4, 0, time.UTC)), ), `{ "val": "2000-02-05T04:04:04Z" }`) @@ -222,10 +222,6 @@ func TestMap(t *testing.T) { }) } -type meow struct { - a int -} - func indentJSON(t *testing.T, j string) string { b := &bytes.Buffer{} err := json.Indent(b, []byte(j), "", strings.Repeat(" ", 4)) diff --git a/s_test.go b/s_test.go index 4e3b9e1..19578c9 100644 --- a/s_test.go +++ b/s_test.go @@ -23,5 +23,5 @@ func TestStdlib(t *testing.T) { et, rest, err := entryhuman.StripTimestamp(b.String()) assert.Success(t, "strip timestamp", err) assert.False(t, "timestamp", et.IsZero()) - assert.Equal(t, "entry", " [INFO]\t(stdlib)\t\tTestStdlib\tstdlib\t{\"hi\": \"we\"}\n", rest) + assert.Equal(t, "entry", " [info] (stdlib) stdlib hi=we\n", rest) } diff --git a/sloggers/sloghuman/sloghuman.go b/sloggers/sloghuman/sloghuman.go index b872c74..5247d17 100644 --- a/sloggers/sloghuman/sloghuman.go +++ b/sloggers/sloghuman/sloghuman.go @@ -3,9 +3,11 @@ package sloghuman // import "cdr.dev/slog/sloggers/sloghuman" import ( + "bufio" + "bytes" "context" "io" - "strings" + "sync" "cdr.dev/slog" "cdr.dev/slog/internal/entryhuman" @@ -29,24 +31,40 @@ type humanSink struct { w2 io.Writer } +var bufPool = sync.Pool{ + New: func() interface{} { + return bytes.NewBuffer(make([]byte, 0, 256)) + }, +} + func (s humanSink) LogEntry(ctx context.Context, ent slog.SinkEntry) { - str := entryhuman.Fmt(s.w2, ent) - lines := strings.Split(str, "\n") + buf1 := bufPool.Get().(*bytes.Buffer) + buf1.Reset() + defer bufPool.Put(buf1) + + buf2 := bufPool.Get().(*bytes.Buffer) + buf2.Reset() + defer bufPool.Put(buf2) + + entryhuman.Fmt(buf1, s.w2, ent) + + var ( + i int + sc = bufio.NewScanner(buf1) + ) // We need to add 4 spaces before every field line for readability. // humanfmt doesn't do it for us because the testSink doesn't want // it as *testing.T automatically does it. - fieldsLines := lines[1:] - for i, line := range fieldsLines { - if line == "" { - continue + for ; sc.Scan(); i++ { + if i > 0 && len(sc.Bytes()) > 0 { + buf2.Write([]byte(" ")) } - fieldsLines[i] = strings.Repeat(" ", 2) + line + buf2.Write(sc.Bytes()) + buf2.WriteByte('\n') } - str = strings.Join(lines, "\n") - - s.w.Write("sloghuman", []byte(str+"\n")) + s.w.Write("sloghuman", buf2.Bytes()) } func (s humanSink) Sync() { diff --git a/sloggers/sloghuman/sloghuman_test.go b/sloggers/sloghuman/sloghuman_test.go index 1c26631..9047161 100644 --- a/sloggers/sloghuman/sloghuman_test.go +++ b/sloggers/sloghuman/sloghuman_test.go @@ -3,6 +3,8 @@ package sloghuman_test import ( "bytes" "context" + "fmt" + "os" "testing" "cdr.dev/slog" @@ -24,5 +26,20 @@ func TestMake(t *testing.T) { et, rest, err := entryhuman.StripTimestamp(b.String()) assert.Success(t, "strip timestamp", err) assert.False(t, "timestamp", et.IsZero()) - assert.Equal(t, "entry", " [INFO]\t\tTestMake\t...\t{\"wowow\": \"me\\nyou\"}\n \"msg\": line1\n\n line2\n", rest) + assert.Equal(t, "entry", " [info] ... wowow=\"me\\nyou\"\n msg= line1\n\n line2\n", rest) +} + +func TestVisual(t *testing.T) { + t.Setenv("FORCE_COLOR", "true") + if os.Getenv("TEST_VISUAL") == "" { + t.Skip("TEST_VISUAL not set") + } + + l := slog.Make(sloghuman.Sink(os.Stdout)).Leveled(slog.LevelDebug) + l.Debug(bg, "small potatos", slog.F("aaa", "mmm"), slog.F("bbb", "nnn"), slog.F("age", 24)) + l.Info(bg, "line1\n\nline2", slog.F("wowow", "me\nyou")) + l.Warn(bg, "oops", slog.F("aaa", "mmm")) + l = l.Named("sublogger") + l.Error(bg, "big oops", slog.F("aaa", "mmm"), slog.Error(fmt.Errorf("this happened\nand this"))) + l.Sync() } diff --git a/sloggers/slogtest/assert/assert.go b/sloggers/slogtest/assert/assert.go index e11476f..1e3c456 100644 --- a/sloggers/slogtest/assert/assert.go +++ b/sloggers/slogtest/assert/assert.go @@ -89,5 +89,4 @@ func stringContainsFold(errs, sub string) bool { sub = strings.ToLower(sub) return strings.Contains(errs, sub) - } diff --git a/sloggers/slogtest/assert/assert_test.go b/sloggers/slogtest/assert/assert_test.go index 49f6c02..b483cf3 100644 --- a/sloggers/slogtest/assert/assert_test.go +++ b/sloggers/slogtest/assert/assert_test.go @@ -44,11 +44,10 @@ func TestErrorContains(t *testing.T) { defer func() { recover() simpleassert.Equal(t, "fatals", 1, tb.fatals) - }() assert.ErrorContains(tb, "meow", io.ErrClosedPipe, "eof") - } + func TestSuccess(t *testing.T) { t.Parallel() diff --git a/sloggers/slogtest/t.go b/sloggers/slogtest/t.go index 646a03d..ace01c8 100644 --- a/sloggers/slogtest/t.go +++ b/sloggers/slogtest/t.go @@ -9,6 +9,7 @@ import ( "context" "log" "os" + "strings" "sync" "testing" @@ -73,8 +74,9 @@ func (ts *testSink) LogEntry(ctx context.Context, ent slog.SinkEntry) { return } + var s strings.Builder // The testing package logs to stdout and not stderr. - s := entryhuman.Fmt(os.Stdout, ent) + entryhuman.Fmt(&s, os.Stdout, ent) switch ent.Level { case slog.LevelDebug, slog.LevelInfo, slog.LevelWarn: From cd356cb7843a691f0c0600c2e6cb94ac0d07bf7e Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Tue, 9 May 2023 00:51:53 -0500 Subject: [PATCH 02/24] Don't panic on nil values --- internal/entryhuman/entry.go | 3 +++ internal/entryhuman/entry_test.go | 9 +++++++++ internal/entryhuman/testdata/nil.golden | 1 + 3 files changed, 13 insertions(+) create mode 100644 internal/entryhuman/testdata/nil.golden diff --git a/internal/entryhuman/entry.go b/internal/entryhuman/entry.go index 6c8406d..16db2bd 100644 --- a/internal/entryhuman/entry.go +++ b/internal/entryhuman/entry.go @@ -57,6 +57,9 @@ func reset(w io.Writer, termW io.Writer) { } func formatValue(v interface{}) string { + if v == nil { + return "" + } typ := reflect.TypeOf(v) switch typ.Kind() { case reflect.Struct, reflect.Map: diff --git a/internal/entryhuman/entry_test.go b/internal/entryhuman/entry_test.go index 6c62827..ca3ea37 100644 --- a/internal/entryhuman/entry_test.go +++ b/internal/entryhuman/entry_test.go @@ -86,6 +86,15 @@ func TestEntry(t *testing.T) { ), }, }, + { + "nil", + slog.SinkEntry{ + Level: slog.LevelWarn, + Fields: slog.M( + slog.F("nan", nil), + ), + }, + }, { "bytes", slog.SinkEntry{ diff --git a/internal/entryhuman/testdata/nil.golden b/internal/entryhuman/testdata/nil.golden new file mode 100644 index 0000000..86b6330 --- /dev/null +++ b/internal/entryhuman/testdata/nil.golden @@ -0,0 +1 @@ +0001-01-01 00:00:00.000 [warn] nan= \ No newline at end of file From ec11fd4615276033f25774ba06ac85b283318b65 Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Tue, 9 May 2023 15:54:28 -0500 Subject: [PATCH 03/24] Calm down sublogger style (#171) * Fix test logger --- internal/entryhuman/entry.go | 8 +++----- internal/entryhuman/entry_test.go | 6 +++++- internal/entryhuman/testdata/named.golden | 2 +- s_test.go | 2 +- sloggers/slogtest/t.go | 6 ++++-- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/internal/entryhuman/entry.go b/internal/entryhuman/entry.go index 16db2bd..3c3ec35 100644 --- a/internal/entryhuman/entry.go +++ b/internal/entryhuman/entry.go @@ -38,8 +38,7 @@ const TimeFormat = "2006-01-02 15:04:05.000" var ( renderer = lipgloss.NewRenderer(os.Stdout, termenv.WithUnsafe()) - loggerNameStyle = renderer.NewStyle().Foreground(lipgloss.Color("#A47DFF")) - timeStyle = renderer.NewStyle().Foreground(lipgloss.Color("#606366")) + timeStyle = renderer.NewStyle().Foreground(lipgloss.Color("#606366")) ) func render(w io.Writer, st lipgloss.Style, s string) string { @@ -108,9 +107,8 @@ func Fmt( buf.WriteString(" ") if len(ent.LoggerNames) > 0 { - loggerName := "(" + quoteKey(strings.Join(ent.LoggerNames, ".")) + ")" - buf.WriteString(render(termW, loggerNameStyle, loggerName)) - buf.WriteString(tab) + loggerName := quoteKey(strings.Join(ent.LoggerNames, ".")) + ": " + buf.WriteString(loggerName) } var multilineKey string diff --git a/internal/entryhuman/entry_test.go b/internal/entryhuman/entry_test.go index ca3ea37..b586b86 100644 --- a/internal/entryhuman/entry_test.go +++ b/internal/entryhuman/entry_test.go @@ -64,7 +64,11 @@ func TestEntry(t *testing.T) { "named", slog.SinkEntry{ Level: slog.LevelWarn, - LoggerNames: []string{"named", "meow"}, + LoggerNames: []string{"some", "cat"}, + Message: "meow", + Fields: slog.M( + slog.F("breath", "stinky"), + ), }, }, { diff --git a/internal/entryhuman/testdata/named.golden b/internal/entryhuman/testdata/named.golden index 09efb6e..83867bf 100644 --- a/internal/entryhuman/testdata/named.golden +++ b/internal/entryhuman/testdata/named.golden @@ -1 +1 @@ -0001-01-01 00:00:00.000 [warn] (named.meow) \ No newline at end of file +0001-01-01 00:00:00.000 [warn] some.cat: meow breath=stinky \ No newline at end of file diff --git a/s_test.go b/s_test.go index 19578c9..358282e 100644 --- a/s_test.go +++ b/s_test.go @@ -23,5 +23,5 @@ func TestStdlib(t *testing.T) { et, rest, err := entryhuman.StripTimestamp(b.String()) assert.Success(t, "strip timestamp", err) assert.False(t, "timestamp", et.IsZero()) - assert.Equal(t, "entry", " [info] (stdlib) stdlib hi=we\n", rest) + assert.Equal(t, "entry", " [info] stdlib: stdlib hi=we\n", rest) } diff --git a/sloggers/slogtest/t.go b/sloggers/slogtest/t.go index ace01c8..724a603 100644 --- a/sloggers/slogtest/t.go +++ b/sloggers/slogtest/t.go @@ -74,9 +74,11 @@ func (ts *testSink) LogEntry(ctx context.Context, ent slog.SinkEntry) { return } - var s strings.Builder + var sb strings.Builder // The testing package logs to stdout and not stderr. - entryhuman.Fmt(&s, os.Stdout, ent) + entryhuman.Fmt(&sb, os.Stdout, ent) + + s := sb.String() switch ent.Level { case slog.LevelDebug, slog.LevelInfo, slog.LevelWarn: From 4d60f86d6ad42e23788d137ed201c6527742a289 Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Tue, 9 May 2023 19:45:21 -0500 Subject: [PATCH 04/24] Pretty-print driver.Valuer --- internal/entryhuman/entry.go | 8 ++++++++ internal/entryhuman/entry_test.go | 11 +++++++++++ internal/entryhuman/testdata/driverValue.golden | 1 + 3 files changed, 20 insertions(+) create mode 100644 internal/entryhuman/testdata/driverValue.golden diff --git a/internal/entryhuman/entry.go b/internal/entryhuman/entry.go index 3c3ec35..ef2d204 100644 --- a/internal/entryhuman/entry.go +++ b/internal/entryhuman/entry.go @@ -4,6 +4,7 @@ package entryhuman import ( "bytes" + "database/sql/driver" "encoding/json" "fmt" "io" @@ -56,6 +57,13 @@ func reset(w io.Writer, termW io.Writer) { } func formatValue(v interface{}) string { + if vr, ok := v.(driver.Valuer); ok { + var err error + v, err = vr.Value() + if err != nil { + return fmt.Sprintf("error calling Value: %v", err) + } + } if v == nil { return "" } diff --git a/internal/entryhuman/entry_test.go b/internal/entryhuman/entry_test.go index b586b86..06ba312 100644 --- a/internal/entryhuman/entry_test.go +++ b/internal/entryhuman/entry_test.go @@ -2,6 +2,7 @@ package entryhuman_test import ( "bytes" + "database/sql" "flag" "fmt" "io" @@ -108,6 +109,16 @@ func TestEntry(t *testing.T) { ), }, }, + { + "driverValue", + slog.SinkEntry{ + Level: slog.LevelWarn, + Fields: slog.M( + slog.F("val", sql.NullString{String: "dog", Valid: true}), + slog.F("inval", sql.NullString{String: "cat", Valid: false}), + ), + }, + }, { "object", slog.SinkEntry{ diff --git a/internal/entryhuman/testdata/driverValue.golden b/internal/entryhuman/testdata/driverValue.golden new file mode 100644 index 0000000..e03ace2 --- /dev/null +++ b/internal/entryhuman/testdata/driverValue.golden @@ -0,0 +1 @@ +0001-01-01 00:00:00.000 [warn] val=dog inval= \ No newline at end of file From fd83a3567145b5f6fb420d911620938d9214ede7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 May 2023 15:33:24 -0500 Subject: [PATCH 05/24] chore: bump golang.org/x/crypto (#174) Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.0.0-20200622213623-75b288015ac9 to 0.9.0. - [Commits](https://github.com/golang/crypto/commits/v0.9.0) --- updated-dependencies: - dependency-name: golang.org/x/crypto dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 9 +++++---- go.sum | 15 ++++++++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index c1fd46d..4ae699e 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/muesli/termenv v0.15.1 go.opencensus.io v0.24.0 go.uber.org/goleak v1.2.1 - golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 + golang.org/x/crypto v0.9.0 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 ) @@ -23,9 +23,10 @@ require ( github.com/mattn/go-runewidth v0.0.14 // indirect github.com/muesli/reflow v0.3.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect - golang.org/x/net v0.0.0-20201110031124-69a78807bb2b // indirect - golang.org/x/sys v0.6.0 // indirect - golang.org/x/text v0.3.3 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect + golang.org/x/term v0.8.0 // indirect + golang.org/x/text v0.9.0 // indirect google.golang.org/grpc v1.33.2 // indirect google.golang.org/protobuf v1.25.0 // indirect ) diff --git a/go.sum b/go.sum index 4b64d35..432e70c 100644 --- a/go.sum +++ b/go.sum @@ -66,8 +66,9 @@ go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -77,8 +78,9 @@ golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -88,11 +90,14 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From aa14d1b470ad2e526e0aeb7075f2db6aff825fa5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 16 May 2023 15:40:20 -0500 Subject: [PATCH 06/24] chore: bump cloud.google.com/go from 0.26.0 to 0.110.2 (#175) Bumps [cloud.google.com/go](https://github.com/googleapis/google-cloud-go) from 0.26.0 to 0.110.2. - [Release notes](https://github.com/googleapis/google-cloud-go/releases) - [Changelog](https://github.com/googleapis/google-cloud-go/blob/main/CHANGES.md) - [Commits](https://github.com/googleapis/google-cloud-go/compare/v0.26.0...v0.110.2) --- updated-dependencies: - dependency-name: cloud.google.com/go dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 17 ++++++++++------- go.sum | 31 ++++++++++++++++++++++++------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index 4ae699e..d67cdd1 100644 --- a/go.mod +++ b/go.mod @@ -3,21 +3,24 @@ module cdr.dev/slog go 1.20 require ( - cloud.google.com/go v0.26.0 + cloud.google.com/go/compute/metadata v0.2.3 github.com/charmbracelet/lipgloss v0.7.1 - github.com/google/go-cmp v0.5.3 + github.com/google/go-cmp v0.5.9 github.com/muesli/termenv v0.15.1 go.opencensus.io v0.24.0 go.uber.org/goleak v1.2.1 golang.org/x/crypto v0.9.0 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 - google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 + google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 ) require ( + cloud.google.com/go/compute v1.19.0 // indirect + cloud.google.com/go/logging v1.7.0 // indirect + cloud.google.com/go/longrunning v0.4.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect - github.com/golang/protobuf v1.4.3 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect @@ -27,6 +30,6 @@ require ( golang.org/x/sys v0.8.0 // indirect golang.org/x/term v0.8.0 // indirect golang.org/x/text v0.9.0 // indirect - google.golang.org/grpc v1.33.2 // indirect - google.golang.org/protobuf v1.25.0 // indirect + google.golang.org/grpc v1.55.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect ) diff --git a/go.sum b/go.sum index 432e70c..ed2541f 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,12 @@ -cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go/compute v1.19.0 h1:+9zda3WGgW1ZSTlVppLCYFIr48Pa35q1uG2N1itbCEQ= +cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= +cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= +cloud.google.com/go/logging v1.7.0 h1:CJYxlNNNNAMkHp9em/YEXcfJg+rPDg7YfwoRpMU+t5I= +cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= +cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= +cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= @@ -16,8 +23,9 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -27,15 +35,19 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= @@ -110,14 +122,16 @@ google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9Ywl google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= +google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -126,8 +140,11 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From 2202bcfb5ef2f7d5cf82de9b1dc46fe99e20ee1c Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 16 May 2023 23:40:41 +0300 Subject: [PATCH 07/24] fix: Use SyscallConn for isTTY which is safe during file close (#167) Co-authored-by: Ammar Bandukwala --- internal/entryhuman/entry.go | 23 ++++++++++++++++++++--- internal/entryhuman/entry_test.go | 29 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 3 deletions(-) diff --git a/internal/entryhuman/entry.go b/internal/entryhuman/entry.go index ef2d204..36c28f8 100644 --- a/internal/entryhuman/entry.go +++ b/internal/entryhuman/entry.go @@ -12,6 +12,7 @@ import ( "reflect" "strconv" "strings" + "syscall" "time" "unicode" @@ -225,9 +226,25 @@ func isTTY(w io.Writer) bool { if w == forceColorWriter { return true } - f, ok := w.(interface { - Fd() uintptr - }) + // SyscallConn is safe during file close. + if sc, ok := w.(interface { + SyscallConn() (syscall.RawConn, error) + }); ok { + conn, err := sc.SyscallConn() + if err != nil { + return false + } + var isTerm bool + err = conn.Control(func(fd uintptr) { + isTerm = terminal.IsTerminal(int(fd)) + }) + if err != nil { + return false + } + return isTerm + } + // Fallback to unsafe Fd. + f, ok := w.(interface{ Fd() uintptr }) return ok && terminal.IsTerminal(int(f.Fd())) } diff --git a/internal/entryhuman/entry_test.go b/internal/entryhuman/entry_test.go index 06ba312..87ddbe2 100644 --- a/internal/entryhuman/entry_test.go +++ b/internal/entryhuman/entry_test.go @@ -6,6 +6,7 @@ import ( "flag" "fmt" "io" + "io/ioutil" "os" "testing" "time" @@ -178,6 +179,34 @@ func TestEntry(t *testing.T) { assert.Equal(t, "entry matches", string(wantByt), gotBuf.String()) }) } + + t.Run("isTTY during file close", func(t *testing.T) { + t.Parallel() + + tmpdir := t.TempDir() + f, err := ioutil.TempFile(tmpdir, "slog") + if err != nil { + t.Fatal(err) + } + defer f.Close() + + done := make(chan struct{}, 2) + go func() { + entryhuman.Fmt(new(bytes.Buffer), f, slog.SinkEntry{ + Level: slog.LevelCritical, + Fields: slog.M( + slog.F("hey", "hi"), + ), + }) + done <- struct{}{} + }() + go func() { + _ = f.Close() + done <- struct{}{} + }() + <-done + <-done + }) } func BenchmarkFmt(b *testing.B) { From c17dfd2b67721d29cf53a0af1e9f0ba0766b91ba Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Tue, 23 May 2023 15:31:21 -0500 Subject: [PATCH 08/24] Support keysAndArgs API of stdlib slog (#173) --- s.go | 2 +- slog.go | 66 +++++++++++++++++++++++++++++++++++++----- slog_test.go | 35 ++++++++++++++++++++-- sloggers/slogtest/t.go | 8 ++--- 4 files changed, 97 insertions(+), 14 deletions(-) diff --git a/s.go b/s.go index 250a003..c6d5df9 100644 --- a/s.go +++ b/s.go @@ -41,7 +41,7 @@ func (w stdlogWriter) Write(p []byte) (n int, err error) { // we do not want. msg = strings.TrimSuffix(msg, "\n") - w.l.log(w.ctx, w.level, msg, Map{}) + w.l.log(w.ctx, w.level, msg, nil) return len(p), nil } diff --git a/slog.go b/slog.go index adea6e2..4e901ae 100644 --- a/slog.go +++ b/slog.go @@ -80,40 +80,67 @@ func Make(sinks ...Sink) Logger { } // Debug logs the msg and fields at LevelDebug. -func (l Logger) Debug(ctx context.Context, msg string, fields ...Field) { +// See Info for information on the fields argument. +func (l Logger) Debug(ctx context.Context, msg string, fields ...any) { l.log(ctx, LevelDebug, msg, fields) } // Info logs the msg and fields at LevelInfo. -func (l Logger) Info(ctx context.Context, msg string, fields ...Field) { +// Fields may contain any combination of key value pairs, Field, and Map. +// For example: +// +// log.Info(ctx, "something happened", "user", "alex", slog.F("age", 20)) +// +// is equivalent to: +// +// log.Info(ctx, "something happened", slog.F("user", "alex"), slog.F("age", 20)) +// +// is equivalent to: +// +// log.Info(ctx, "something happened", slog.M( +// slog.F("user", "alex"), +// slog.F("age", 20), +// )) +// +// is equivalent to: +// +// log.Info(ctx, "something happened", "user", "alex", "age", 20) +// +// In general, prefer using key value pairs over Field and Map, as that is how +// the standard library's slog package works. +func (l Logger) Info(ctx context.Context, msg string, fields ...any) { l.log(ctx, LevelInfo, msg, fields) } // Warn logs the msg and fields at LevelWarn. -func (l Logger) Warn(ctx context.Context, msg string, fields ...Field) { +// See Info() for information on the fields argument. +func (l Logger) Warn(ctx context.Context, msg string, fields ...any) { l.log(ctx, LevelWarn, msg, fields) } // Error logs the msg and fields at LevelError. +// See Info() for information on the fields argument. // // It will then Sync(). -func (l Logger) Error(ctx context.Context, msg string, fields ...Field) { +func (l Logger) Error(ctx context.Context, msg string, fields ...any) { l.log(ctx, LevelError, msg, fields) l.Sync() } // Critical logs the msg and fields at LevelCritical. +// See Info() for information on the fields argument. // // It will then Sync(). -func (l Logger) Critical(ctx context.Context, msg string, fields ...Field) { +func (l Logger) Critical(ctx context.Context, msg string, fields ...any) { l.log(ctx, LevelCritical, msg, fields) l.Sync() } // Fatal logs the msg and fields at LevelFatal. +// See Info() for information on the fields argument. // // It will then Sync() and os.Exit(1). -func (l Logger) Fatal(ctx context.Context, msg string, fields ...Field) { +func (l Logger) Fatal(ctx context.Context, msg string, fields ...any) { l.log(ctx, LevelFatal, msg, fields) l.Sync() @@ -155,7 +182,32 @@ func (l Logger) AppendSinks(s ...Sink) Logger { return l } -func (l Logger) log(ctx context.Context, level Level, msg string, fields Map) { +func (l Logger) log(ctx context.Context, level Level, msg string, rawFields []any) { + fields := make(Map, 0, len(rawFields)) + var wipField Field + for i, f := range rawFields { + if wipField.Name != "" { + wipField.Value = f + fields = append(fields, wipField) + wipField = Field{} + continue + } + switch f := f.(type) { + case Field: + fields = append(fields, f) + case Map: + fields = append(fields, f...) + case string: + wipField.Name = f + default: + panic(fmt.Sprintf("unexpected field type %T at index %v (does it have a key?)", f, i)) + } + } + + if wipField.Name != "" { + panic(fmt.Sprintf("field %q has no value", wipField.Name)) + } + ent := l.entry(ctx, level, msg, fields) l.Log(ctx, ent) } diff --git a/slog_test.go b/slog_test.go index b708b51..7793b17 100644 --- a/slog_test.go +++ b/slog_test.go @@ -2,6 +2,7 @@ package slog_test import ( "context" + "fmt" "io" "runtime" "testing" @@ -75,7 +76,7 @@ func TestLogger(t *testing.T) { File: slogTestFile, Func: "cdr.dev/slog_test.TestLogger.func2", - Line: 67, + Line: 68, Fields: slog.M( slog.F("ctx", 1024), @@ -108,7 +109,7 @@ func TestLogger(t *testing.T) { File: slogTestFile, Func: "cdr.dev/slog_test.TestLogger.func3", - Line: 98, + Line: 99, SpanContext: span.SpanContext(), @@ -149,6 +150,36 @@ func TestLogger(t *testing.T) { assert.Equal(t, "level", slog.LevelFatal, s.entries[5].Level) assert.Equal(t, "exits", 1, exits) }) + + t.Run("kv", func(t *testing.T) { + s := &fakeSink{} + l := slog.Make(s) + + // All of these formats should be equivalent. + formats := [][]any{ + {"animal", "cat", "weight", 15}, + {slog.F("animal", "cat"), "weight", 15}, + {slog.M( + slog.F("animal", "cat"), + slog.F("weight", 15), + )}, + {slog.F("animal", "cat"), slog.F("weight", 15)}, + } + + for _, format := range formats { + l.Info(bg, "msg", format...) + } + + assert.Len(t, "entries", 4, s.entries) + + for i := range s.entries { + assert.Equal( + t, fmt.Sprintf("%v", i), + s.entries[0].Fields, + s.entries[i].Fields, + ) + } + }) } func TestLevel_String(t *testing.T) { diff --git a/sloggers/slogtest/t.go b/sloggers/slogtest/t.go index 724a603..9d81766 100644 --- a/sloggers/slogtest/t.go +++ b/sloggers/slogtest/t.go @@ -103,25 +103,25 @@ func l(t testing.TB) slog.Logger { } // Debug logs the given msg and fields to t via t.Log at the debug level. -func Debug(t testing.TB, msg string, fields ...slog.Field) { +func Debug(t testing.TB, msg string, fields ...any) { slog.Helper() l(t).Debug(ctx, msg, fields...) } // Info logs the given msg and fields to t via t.Log at the info level. -func Info(t testing.TB, msg string, fields ...slog.Field) { +func Info(t testing.TB, msg string, fields ...any) { slog.Helper() l(t).Info(ctx, msg, fields...) } // Error logs the given msg and fields to t via t.Error at the error level. -func Error(t testing.TB, msg string, fields ...slog.Field) { +func Error(t testing.TB, msg string, fields ...any) { slog.Helper() l(t).Error(ctx, msg, fields...) } // Fatal logs the given msg and fields to t via t.Fatal at the fatal level. -func Fatal(t testing.TB, msg string, fields ...slog.Field) { +func Fatal(t testing.TB, msg string, fields ...any) { slog.Helper() l(t).Fatal(ctx, msg, fields...) } From a39d36c4badd2f545ea4e07cedaccff601fcbc73 Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Tue, 30 May 2023 17:19:15 +0000 Subject: [PATCH 09/24] Update GCP deps --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d67cdd1..deb77ce 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( ) require ( - cloud.google.com/go/compute v1.19.0 // indirect + cloud.google.com/go/compute v1.19.3 // indirect cloud.google.com/go/logging v1.7.0 // indirect cloud.google.com/go/longrunning v0.4.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect diff --git a/go.sum b/go.sum index ed2541f..83bf1ce 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go/compute v1.19.0 h1:+9zda3WGgW1ZSTlVppLCYFIr48Pa35q1uG2N1itbCEQ= -cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= +cloud.google.com/go/compute v1.19.3 h1:DcTwsFgGev/wV5+q8o2fzgcHOaac+DKGC91ZlvpsQds= +cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/logging v1.7.0 h1:CJYxlNNNNAMkHp9em/YEXcfJg+rPDg7YfwoRpMU+t5I= From 5275fa74f12c1a1f3604b7cb35adc8269f1c9d92 Mon Sep 17 00:00:00 2001 From: Ammar Bandukwala Date: Tue, 30 May 2023 14:22:15 -0500 Subject: [PATCH 10/24] Revert "fix: Use SyscallConn for isTTY which is safe during file close (#167)" This reverts commit 2202bcfb5ef2f7d5cf82de9b1dc46fe99e20ee1c. See https://github.com/coder/slog/issues/176 --- internal/entryhuman/entry.go | 23 +++-------------------- internal/entryhuman/entry_test.go | 29 ----------------------------- 2 files changed, 3 insertions(+), 49 deletions(-) diff --git a/internal/entryhuman/entry.go b/internal/entryhuman/entry.go index 36c28f8..ef2d204 100644 --- a/internal/entryhuman/entry.go +++ b/internal/entryhuman/entry.go @@ -12,7 +12,6 @@ import ( "reflect" "strconv" "strings" - "syscall" "time" "unicode" @@ -226,25 +225,9 @@ func isTTY(w io.Writer) bool { if w == forceColorWriter { return true } - // SyscallConn is safe during file close. - if sc, ok := w.(interface { - SyscallConn() (syscall.RawConn, error) - }); ok { - conn, err := sc.SyscallConn() - if err != nil { - return false - } - var isTerm bool - err = conn.Control(func(fd uintptr) { - isTerm = terminal.IsTerminal(int(fd)) - }) - if err != nil { - return false - } - return isTerm - } - // Fallback to unsafe Fd. - f, ok := w.(interface{ Fd() uintptr }) + f, ok := w.(interface { + Fd() uintptr + }) return ok && terminal.IsTerminal(int(f.Fd())) } diff --git a/internal/entryhuman/entry_test.go b/internal/entryhuman/entry_test.go index 87ddbe2..06ba312 100644 --- a/internal/entryhuman/entry_test.go +++ b/internal/entryhuman/entry_test.go @@ -6,7 +6,6 @@ import ( "flag" "fmt" "io" - "io/ioutil" "os" "testing" "time" @@ -179,34 +178,6 @@ func TestEntry(t *testing.T) { assert.Equal(t, "entry matches", string(wantByt), gotBuf.String()) }) } - - t.Run("isTTY during file close", func(t *testing.T) { - t.Parallel() - - tmpdir := t.TempDir() - f, err := ioutil.TempFile(tmpdir, "slog") - if err != nil { - t.Fatal(err) - } - defer f.Close() - - done := make(chan struct{}, 2) - go func() { - entryhuman.Fmt(new(bytes.Buffer), f, slog.SinkEntry{ - Level: slog.LevelCritical, - Fields: slog.M( - slog.F("hey", "hi"), - ), - }) - done <- struct{}{} - }() - go func() { - _ = f.Close() - done <- struct{}{} - }() - <-done - <-done - }) } func BenchmarkFmt(b *testing.B) { From c10058d3253185deec4773188ab014071eca0af5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Jul 2023 10:55:31 -0500 Subject: [PATCH 11/24] chore: bump golang.org/x/crypto from 0.9.0 to 0.11.0 (#179) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index deb77ce..b1e1e9b 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/muesli/termenv v0.15.1 go.opencensus.io v0.24.0 go.uber.org/goleak v1.2.1 - golang.org/x/crypto v0.9.0 + golang.org/x/crypto v0.11.0 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 ) @@ -27,9 +27,9 @@ require ( github.com/muesli/reflow v0.3.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/term v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/term v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect google.golang.org/grpc v1.55.0 // indirect google.golang.org/protobuf v1.30.0 // indirect ) diff --git a/go.sum b/go.sum index 83bf1ce..06282d2 100644 --- a/go.sum +++ b/go.sum @@ -79,8 +79,8 @@ go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -102,14 +102,14 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= -golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= From 28eb7242131ac8e091b4c39571ad2ff8df62134a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 31 Jul 2023 11:35:46 -0500 Subject: [PATCH 12/24] chore: bump github.com/muesli/termenv from 0.15.1 to 0.15.2 (#178) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index b1e1e9b..eff1314 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 github.com/charmbracelet/lipgloss v0.7.1 github.com/google/go-cmp v0.5.9 - github.com/muesli/termenv v0.15.1 + github.com/muesli/termenv v0.15.2 go.opencensus.io v0.24.0 go.uber.org/goleak v1.2.1 golang.org/x/crypto v0.11.0 @@ -22,7 +22,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.18 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/muesli/reflow v0.3.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect diff --git a/go.sum b/go.sum index 06282d2..74f291e 100644 --- a/go.sum +++ b/go.sum @@ -51,15 +51,15 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= +github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= -github.com/muesli/termenv v0.15.1 h1:UzuTb/+hhlBugQz28rpzey4ZuKcZ03MeKsoG7IJZIxs= -github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ= +github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= +github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -101,7 +101,7 @@ golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= From 2e3b402dc2592700e4a87c645af453ea6d71279f Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Mon, 31 Jul 2023 13:04:57 -0500 Subject: [PATCH 13/24] chore: migrate to `go.opentelemetry.io` tracing (#181) --- .github/dependabot.yml | 4 + go.mod | 10 +- go.sum | 108 +++--------------- internal/entryhuman/entry.go | 3 +- slog.go | 4 +- slog_test.go | 10 +- sloggers/slogjson/slogjson.go | 8 +- sloggers/slogjson/slogjson_test.go | 12 +- sloggers/slogstackdriver/slogstackdriver.go | 24 ++-- .../slogstackdriver/slogstackdriver_test.go | 32 +++++- 10 files changed, 87 insertions(+), 128 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ebbc08a..6b4085e 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -21,3 +21,7 @@ updates: timezone: "America/Chicago" commit-message: prefix: "chore" + groups: + otel: + patterns: + - "go.opentelemetry.io/*" diff --git a/go.mod b/go.mod index eff1314..95ba8d2 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,12 @@ go 1.20 require ( cloud.google.com/go/compute/metadata v0.2.3 + cloud.google.com/go/logging v1.7.0 github.com/charmbracelet/lipgloss v0.7.1 github.com/google/go-cmp v0.5.9 github.com/muesli/termenv v0.15.2 - go.opencensus.io v0.24.0 + go.opentelemetry.io/otel/sdk v1.16.0 + go.opentelemetry.io/otel/trace v1.16.0 go.uber.org/goleak v1.2.1 golang.org/x/crypto v0.11.0 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 @@ -16,16 +18,18 @@ require ( require ( cloud.google.com/go/compute v1.19.3 // indirect - cloud.google.com/go/logging v1.7.0 // indirect cloud.google.com/go/longrunning v0.4.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-isatty v0.0.18 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/muesli/reflow v0.3.0 // indirect github.com/rivo/uniseg v0.2.0 // indirect + go.opentelemetry.io/otel v1.16.0 // indirect + go.opentelemetry.io/otel/metric v1.16.0 // indirect golang.org/x/net v0.10.0 // indirect golang.org/x/sys v0.10.0 // indirect golang.org/x/term v0.10.0 // indirect diff --git a/go.sum b/go.sum index 74f291e..a3e9baa 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go/compute v1.19.3 h1:DcTwsFgGev/wV5+q8o2fzgcHOaac+DKGC91ZlvpsQds= cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= @@ -7,48 +6,22 @@ cloud.google.com/go/logging v1.7.0 h1:CJYxlNNNNAMkHp9em/YEXcfJg+rPDg7YfwoRpMU+t5 cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= -github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/charmbracelet/lipgloss v0.7.1 h1:17WMwi7N1b1rVWOjMT+rCh7sQkvDU75B2hbZpc5Kc1E= github.com/charmbracelet/lipgloss v0.7.1/go.mod h1:yG0k3giv8Qj8edTCbbg6AlQ5e8KNWpFujkNawKNhE2c= -github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= @@ -61,93 +34,40 @@ github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKt github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= +go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= +go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= +go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= +go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE= +go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= +go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= +go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= -golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= -golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/entryhuman/entry.go b/internal/entryhuman/entry.go index ef2d204..a6d30f9 100644 --- a/internal/entryhuman/entry.go +++ b/internal/entryhuman/entry.go @@ -17,7 +17,6 @@ import ( "github.com/charmbracelet/lipgloss" "github.com/muesli/termenv" - "go.opencensus.io/trace" "golang.org/x/crypto/ssh/terminal" "golang.org/x/xerrors" @@ -130,7 +129,7 @@ func Fmt( } buf.WriteString(msg) - if ent.SpanContext != (trace.SpanContext{}) { + if ent.SpanContext.IsValid() { ent.Fields = append(slog.M( slog.F("trace", ent.SpanContext.TraceID), slog.F("span", ent.SpanContext.SpanID), diff --git a/slog.go b/slog.go index 4e901ae..a3b705c 100644 --- a/slog.go +++ b/slog.go @@ -18,7 +18,7 @@ import ( "sync" "time" - "go.opencensus.io/trace" + "go.opentelemetry.io/otel/trace" ) var defaultExitFn = os.Exit @@ -218,7 +218,7 @@ func (l Logger) entry(ctx context.Context, level Level, msg string, fields Map) Level: level, Message: msg, Fields: fieldsFromContext(ctx).append(fields), - SpanContext: trace.FromContext(ctx).SpanContext(), + SpanContext: trace.SpanContextFromContext(ctx), } ent = ent.fillLoc(l.skip + 3) return ent diff --git a/slog_test.go b/slog_test.go index 7793b17..277a9c3 100644 --- a/slog_test.go +++ b/slog_test.go @@ -7,7 +7,7 @@ import ( "runtime" "testing" - "go.opencensus.io/trace" + sdktrace "go.opentelemetry.io/otel/sdk/trace" "cdr.dev/slog" "cdr.dev/slog/internal/assert" @@ -92,7 +92,11 @@ func TestLogger(t *testing.T) { l = l.Named("hello") l = l.Named("hello2") - ctx, span := trace.StartSpan(bg, "trace") + tp := sdktrace.NewTracerProvider() + tracer := tp.Tracer("tracer") + ctx, span := tracer.Start(bg, "trace") + span.End() + _ = tp.Shutdown(bg) ctx = slog.With(ctx, slog.F("ctx", io.EOF)) l = l.With(slog.F("with", 2)) @@ -109,7 +113,7 @@ func TestLogger(t *testing.T) { File: slogTestFile, Func: "cdr.dev/slog_test.TestLogger.func3", - Line: 99, + Line: 103, SpanContext: span.SpanContext(), diff --git a/sloggers/slogjson/slogjson.go b/sloggers/slogjson/slogjson.go index 5a5d4ae..d38ee89 100644 --- a/sloggers/slogjson/slogjson.go +++ b/sloggers/slogjson/slogjson.go @@ -23,8 +23,6 @@ import ( "fmt" "io" - "go.opencensus.io/trace" - "cdr.dev/slog" "cdr.dev/slog/internal/syncwriter" ) @@ -57,10 +55,10 @@ func (s jsonSink) LogEntry(ctx context.Context, ent slog.SinkEntry) { m = append(m, slog.F("logger_names", ent.LoggerNames)) } - if ent.SpanContext != (trace.SpanContext{}) { + if ent.SpanContext.IsValid() { m = append(m, - slog.F("trace", ent.SpanContext.TraceID), - slog.F("span", ent.SpanContext.SpanID), + slog.F("trace", ent.SpanContext.TraceID()), + slog.F("span", ent.SpanContext.SpanID()), ) } diff --git a/sloggers/slogjson/slogjson_test.go b/sloggers/slogjson/slogjson_test.go index 46f8590..79a46e7 100644 --- a/sloggers/slogjson/slogjson_test.go +++ b/sloggers/slogjson/slogjson_test.go @@ -7,7 +7,7 @@ import ( "runtime" "testing" - "go.opencensus.io/trace" + sdktrace "go.opentelemetry.io/otel/sdk/trace" "cdr.dev/slog" "cdr.dev/slog/internal/assert" @@ -22,14 +22,18 @@ var bg = context.Background() func TestMake(t *testing.T) { t.Parallel() - ctx, s := trace.StartSpan(bg, "meow") + tp := sdktrace.NewTracerProvider() + tracer := tp.Tracer("tracer") + ctx, span := tracer.Start(bg, "trace") + span.End() + _ = tp.Shutdown(bg) b := &bytes.Buffer{} l := slog.Make(slogjson.Sink(b)) l = l.Named("named") l.Error(ctx, "line1\n\nline2", slog.F("wowow", "me\nyou")) j := entryjson.Filter(b.String(), "ts") - exp := fmt.Sprintf(`{"level":"ERROR","msg":"line1\n\nline2","caller":"%v:29","func":"cdr.dev/slog/sloggers/slogjson_test.TestMake","logger_names":["named"],"trace":"%v","span":"%v","fields":{"wowow":"me\nyou"}} -`, slogjsonTestFile, s.SpanContext().TraceID, s.SpanContext().SpanID) + exp := fmt.Sprintf(`{"level":"ERROR","msg":"line1\n\nline2","caller":"%v:33","func":"cdr.dev/slog/sloggers/slogjson_test.TestMake","logger_names":["named"],"trace":"%v","span":"%v","fields":{"wowow":"me\nyou"}} +`, slogjsonTestFile, span.SpanContext().TraceID().String(), span.SpanContext().SpanID().String()) assert.Equal(t, "entry", exp, j) } diff --git a/sloggers/slogstackdriver/slogstackdriver.go b/sloggers/slogstackdriver/slogstackdriver.go index 9223c26..f9eed55 100644 --- a/sloggers/slogstackdriver/slogstackdriver.go +++ b/sloggers/slogstackdriver/slogstackdriver.go @@ -11,9 +11,9 @@ import ( "time" "cloud.google.com/go/compute/metadata" - "go.opencensus.io/trace" + "cloud.google.com/go/logging/apiv2/loggingpb" + "go.opentelemetry.io/otel/trace" logpbtype "google.golang.org/genproto/googleapis/logging/type" - logpb "google.golang.org/genproto/googleapis/logging/v2" "cdr.dev/slog" "cdr.dev/slog/internal/syncwriter" @@ -29,10 +29,14 @@ func Sink(w io.Writer) slog.Sink { // // We use a very short timeout because the metadata server should be // within the same datacenter as the cloud instance. - client := metadata.NewClient(&http.Client{ - Timeout: time.Second * 3, - }) + tp := http.DefaultTransport.(*http.Transport).Clone() + httpClient := &http.Client{ + Timeout: time.Second * 3, + Transport: tp, + } + client := metadata.NewClient(httpClient) projectID, _ := client.ProjectID() + httpClient.CloseIdleConnections() return stackdriverSink{ projectID: projectID, @@ -56,7 +60,7 @@ func (s stackdriverSink) LogEntry(ctx context.Context, ent slog.SinkEntry) { // Unfortunately, both of these fields are required. slog.F("timestampSeconds", ent.Time.Unix()), slog.F("timestampNanos", ent.Time.UnixNano()%1e9), - slog.F("logging.googleapis.com/sourceLocation", &logpb.LogEntrySourceLocation{ + slog.F("logging.googleapis.com/sourceLocation", &loggingpb.LogEntrySourceLocation{ File: ent.File, Line: int64(ent.Line), Function: ent.Func, @@ -64,15 +68,15 @@ func (s stackdriverSink) LogEntry(ctx context.Context, ent slog.SinkEntry) { ) if len(ent.LoggerNames) > 0 { - e = append(e, slog.F("logging.googleapis.com/operation", &logpb.LogEntryOperation{ + e = append(e, slog.F("logging.googleapis.com/operation", &loggingpb.LogEntryOperation{ Producer: strings.Join(ent.LoggerNames, "."), })) } - if ent.SpanContext != (trace.SpanContext{}) { + if ent.SpanContext.IsValid() { e = append(e, - slog.F("logging.googleapis.com/trace", s.traceField(ent.SpanContext.TraceID)), - slog.F("logging.googleapis.com/spanId", ent.SpanContext.SpanID.String()), + slog.F("logging.googleapis.com/trace", s.traceField(ent.SpanContext.TraceID())), + slog.F("logging.googleapis.com/spanId", ent.SpanContext.SpanID().String()), slog.F("logging.googleapis.com/trace_sampled", ent.SpanContext.IsSampled()), ) } diff --git a/sloggers/slogstackdriver/slogstackdriver_test.go b/sloggers/slogstackdriver/slogstackdriver_test.go index 11a0934..ec58ba7 100644 --- a/sloggers/slogstackdriver/slogstackdriver_test.go +++ b/sloggers/slogstackdriver/slogstackdriver_test.go @@ -4,13 +4,15 @@ import ( "bytes" "context" "fmt" + "net/http" "runtime" "testing" + "time" "go.uber.org/goleak" "cloud.google.com/go/compute/metadata" - "go.opencensus.io/trace" + sdktrace "go.opentelemetry.io/otel/sdk/trace" logpbtype "google.golang.org/genproto/googleapis/logging/type" "cdr.dev/slog" @@ -27,18 +29,22 @@ var ( func TestStackdriver(t *testing.T) { t.Parallel() - ctx, s := trace.StartSpan(bg, "meow") + tp := sdktrace.NewTracerProvider() + tracer := tp.Tracer("tracer") + ctx, span := tracer.Start(bg, "trace") + span.End() + _ = tp.Shutdown(bg) b := &bytes.Buffer{} l := slog.Make(slogstackdriver.Sink(b)) l = l.Named("meow") l.Error(ctx, "line1\n\nline2", slog.F("wowow", "me\nyou")) - projectID, _ := metadata.ProjectID() + projectID, _ := metadataClient(t).ProjectID() j := entryjson.Filter(b.String(), "timestampSeconds") j = entryjson.Filter(j, "timestampNanos") - exp := fmt.Sprintf(`{"logging.googleapis.com/severity":"ERROR","message":"line1\n\nline2","logging.googleapis.com/sourceLocation":{"file":"%v","line":34,"function":"cdr.dev/slog/sloggers/slogstackdriver_test.TestStackdriver"},"logging.googleapis.com/operation":{"producer":"meow"},"logging.googleapis.com/trace":"projects/%v/traces/%v","logging.googleapis.com/spanId":"%v","logging.googleapis.com/trace_sampled":false,"wowow":"me\nyou"} -`, slogstackdriverTestFile, projectID, s.SpanContext().TraceID, s.SpanContext().SpanID) + exp := fmt.Sprintf(`{"logging.googleapis.com/severity":"ERROR","message":"line1\n\nline2","logging.googleapis.com/sourceLocation":{"file":"%v","line":40,"function":"cdr.dev/slog/sloggers/slogstackdriver_test.TestStackdriver"},"logging.googleapis.com/operation":{"producer":"meow"},"logging.googleapis.com/trace":"projects/%v/traces/%v","logging.googleapis.com/spanId":"%v","logging.googleapis.com/trace_sampled":%v,"wowow":"me\nyou"} +`, slogstackdriverTestFile, projectID, span.SpanContext().TraceID(), span.SpanContext().SpanID(), span.SpanContext().IsSampled()) assert.Equal(t, "entry", exp, j) } @@ -55,3 +61,19 @@ func TestSevMapping(t *testing.T) { func TestMain(m *testing.M) { goleak.VerifyTestMain(m) } + +func metadataClient(t testing.TB) *metadata.Client { + // When not running in Google Cloud, the default metadata client will + // leak a goroutine. + // + // We use a very short timeout because the metadata server should be + // within the same datacenter as the cloud instance. + tp := http.DefaultTransport.(*http.Transport).Clone() + httpClient := &http.Client{ + Timeout: time.Second * 3, + Transport: tp, + } + client := metadata.NewClient(httpClient) + t.Cleanup(httpClient.CloseIdleConnections) + return client +} From ea050d3835b22c91adc925ebfe822d936db4ab90 Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Mon, 31 Jul 2023 13:54:36 -0500 Subject: [PATCH 14/24] chore: update all deps (#182) --- go.mod | 20 +++++++++++--------- go.sum | 39 ++++++++++++++++++++++----------------- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/go.mod b/go.mod index 95ba8d2..11fe29f 100644 --- a/go.mod +++ b/go.mod @@ -13,27 +13,29 @@ require ( go.uber.org/goleak v1.2.1 golang.org/x/crypto v0.11.0 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 - google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 + google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e ) require ( - cloud.google.com/go/compute v1.19.3 // indirect - cloud.google.com/go/longrunning v0.4.1 // indirect + cloud.google.com/go/compute v1.23.0 // indirect + cloud.google.com/go/longrunning v0.5.1 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - github.com/mattn/go-isatty v0.0.18 // indirect - github.com/mattn/go-runewidth v0.0.14 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-runewidth v0.0.15 // indirect github.com/muesli/reflow v0.3.0 // indirect - github.com/rivo/uniseg v0.2.0 // indirect + github.com/rivo/uniseg v0.4.4 // indirect go.opentelemetry.io/otel v1.16.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect - golang.org/x/net v0.10.0 // indirect + golang.org/x/net v0.12.0 // indirect golang.org/x/sys v0.10.0 // indirect golang.org/x/term v0.10.0 // indirect golang.org/x/text v0.11.0 // indirect - google.golang.org/grpc v1.55.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130 // indirect + google.golang.org/grpc v1.57.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect ) diff --git a/go.sum b/go.sum index a3e9baa..a23ef10 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,11 @@ -cloud.google.com/go/compute v1.19.3 h1:DcTwsFgGev/wV5+q8o2fzgcHOaac+DKGC91ZlvpsQds= -cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= +cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= +cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/logging v1.7.0 h1:CJYxlNNNNAMkHp9em/YEXcfJg+rPDg7YfwoRpMU+t5I= cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= -cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM= -cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= +cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI= +cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/charmbracelet/lipgloss v0.7.1 h1:17WMwi7N1b1rVWOjMT+rCh7sQkvDU75B2hbZpc5Kc1E= @@ -24,19 +24,20 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= +github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= @@ -50,8 +51,8 @@ go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -62,12 +63,16 @@ golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= -google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= -google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag= -google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e h1:xIXmWJ303kJCuogpj0bHq+dcjcZHU+XFyc1I0Yl9cRg= +google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:0ggbjUrZYpy1q+ANUS30SEoGZ53cdfwtbuG7Ptgy108= +google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU= +google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130 h1:2FZP5XuJY9zQyGM5N0rtovnoXjiMUEIUMvw0m9wlpLc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:8mL13HKkDa+IuJ8yruA3ci0q+0vsUz4m//+ottjwS5o= +google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= +google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From 5311545a9efdfa7d3a5e99914813bd3ab2e2ed7b Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Mon, 31 Jul 2023 14:12:38 -0500 Subject: [PATCH 15/24] chore: use `golang.org/x/term` (#183) --- go.mod | 3 +-- go.sum | 2 -- internal/entryhuman/entry.go | 4 ++-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 11fe29f..ca6640f 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( go.opentelemetry.io/otel/sdk v1.16.0 go.opentelemetry.io/otel/trace v1.16.0 go.uber.org/goleak v1.2.1 - golang.org/x/crypto v0.11.0 + golang.org/x/term v0.10.0 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e ) @@ -32,7 +32,6 @@ require ( go.opentelemetry.io/otel/metric v1.16.0 // indirect golang.org/x/net v0.12.0 // indirect golang.org/x/sys v0.10.0 // indirect - golang.org/x/term v0.10.0 // indirect golang.org/x/text v0.11.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130 // indirect diff --git a/go.sum b/go.sum index a23ef10..aefa004 100644 --- a/go.sum +++ b/go.sum @@ -49,8 +49,6 @@ go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZE go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/internal/entryhuman/entry.go b/internal/entryhuman/entry.go index a6d30f9..cd63ccb 100644 --- a/internal/entryhuman/entry.go +++ b/internal/entryhuman/entry.go @@ -17,7 +17,7 @@ import ( "github.com/charmbracelet/lipgloss" "github.com/muesli/termenv" - "golang.org/x/crypto/ssh/terminal" + "golang.org/x/term" "golang.org/x/xerrors" "cdr.dev/slog" @@ -227,7 +227,7 @@ func isTTY(w io.Writer) bool { f, ok := w.(interface { Fd() uintptr }) - return ok && terminal.IsTerminal(int(f.Fd())) + return ok && term.IsTerminal(int(f.Fd())) } func shouldColor(w io.Writer) bool { From 9f58760f5b6b9e37993613e25f6778e4850727db Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 15:06:57 -0500 Subject: [PATCH 16/24] chore: bump golang.org/x/term from 0.10.0 to 0.11.0 (#184) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index ca6640f..1435215 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( go.opentelemetry.io/otel/sdk v1.16.0 go.opentelemetry.io/otel/trace v1.16.0 go.uber.org/goleak v1.2.1 - golang.org/x/term v0.10.0 + golang.org/x/term v0.11.0 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 google.golang.org/genproto v0.0.0-20230726155614-23370e0ffb3e ) @@ -31,7 +31,7 @@ require ( go.opentelemetry.io/otel v1.16.0 // indirect go.opentelemetry.io/otel/metric v1.16.0 // indirect golang.org/x/net v0.12.0 // indirect - golang.org/x/sys v0.10.0 // indirect + golang.org/x/sys v0.11.0 // indirect golang.org/x/text v0.11.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230706204954-ccb25ca9f130 // indirect diff --git a/go.sum b/go.sum index aefa004..750857b 100644 --- a/go.sum +++ b/go.sum @@ -52,10 +52,10 @@ go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= -golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= +golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 0830a57ace3f1d1bb73ef823630307bfe993a710 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Aug 2023 15:19:27 -0500 Subject: [PATCH 17/24] chore: bump cloud.google.com/go/logging from 1.7.0 to 1.8.1 (#186) Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1435215..52efddb 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( cloud.google.com/go/compute/metadata v0.2.3 - cloud.google.com/go/logging v1.7.0 + cloud.google.com/go/logging v1.8.1 github.com/charmbracelet/lipgloss v0.7.1 github.com/google/go-cmp v0.5.9 github.com/muesli/termenv v0.15.2 diff --git a/go.sum b/go.sum index 750857b..9eb2fc3 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopT cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/logging v1.7.0 h1:CJYxlNNNNAMkHp9em/YEXcfJg+rPDg7YfwoRpMU+t5I= -cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= +cloud.google.com/go/logging v1.8.1 h1:26skQWPeYhvIasWKm48+Eq7oUqdcdbwsCVwz5Ys0FvU= +cloud.google.com/go/logging v1.8.1/go.mod h1:TJjR+SimHwuC8MZ9cjByQulAMgni+RkXeI3wwctHJEI= cloud.google.com/go/longrunning v0.5.1 h1:Fr7TXftcqTudoyRJa113hyaqlGdiBQkp0Gq7tErFDWI= cloud.google.com/go/longrunning v0.5.1/go.mod h1:spvimkwdz6SPWKEt/XBij79E9fiTkHSQl/fRUUQJYJc= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= From b386d5d10a809d5d5b9d4f45d92236ae980f5979 Mon Sep 17 00:00:00 2001 From: Colin Adler Date: Thu, 17 Aug 2023 15:42:40 -0500 Subject: [PATCH 18/24] =?UTF-8?q?Revert=20"Revert=20"fix:=20Use=20SyscallC?= =?UTF-8?q?onn=20for=20isTTY=20which=20is=20safe=20during=20f=E2=80=A6=20(?= =?UTF-8?q?#187)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/entryhuman/entry.go | 23 ++++++++++++++++++++--- internal/entryhuman/entry_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/internal/entryhuman/entry.go b/internal/entryhuman/entry.go index cd63ccb..8af4d82 100644 --- a/internal/entryhuman/entry.go +++ b/internal/entryhuman/entry.go @@ -12,6 +12,7 @@ import ( "reflect" "strconv" "strings" + "syscall" "time" "unicode" @@ -224,9 +225,25 @@ func isTTY(w io.Writer) bool { if w == forceColorWriter { return true } - f, ok := w.(interface { - Fd() uintptr - }) + // SyscallConn is safe during file close. + if sc, ok := w.(interface { + SyscallConn() (syscall.RawConn, error) + }); ok { + conn, err := sc.SyscallConn() + if err != nil { + return false + } + var isTerm bool + err = conn.Control(func(fd uintptr) { + isTerm = term.IsTerminal(int(fd)) + }) + if err != nil { + return false + } + return isTerm + } + // Fallback to unsafe Fd. + f, ok := w.(interface{ Fd() uintptr }) return ok && term.IsTerminal(int(f.Fd())) } diff --git a/internal/entryhuman/entry_test.go b/internal/entryhuman/entry_test.go index 06ba312..45a885a 100644 --- a/internal/entryhuman/entry_test.go +++ b/internal/entryhuman/entry_test.go @@ -178,6 +178,34 @@ func TestEntry(t *testing.T) { assert.Equal(t, "entry matches", string(wantByt), gotBuf.String()) }) } + + t.Run("isTTY during file close", func(t *testing.T) { + t.Parallel() + + tmpdir := t.TempDir() + f, err := os.CreateTemp(tmpdir, "slog") + if err != nil { + t.Fatal(err) + } + defer f.Close() + + done := make(chan struct{}, 2) + go func() { + entryhuman.Fmt(new(bytes.Buffer), f, slog.SinkEntry{ + Level: slog.LevelCritical, + Fields: slog.M( + slog.F("hey", "hi"), + ), + }) + done <- struct{}{} + }() + go func() { + _ = f.Close() + done <- struct{}{} + }() + <-done + <-done + }) } func BenchmarkFmt(b *testing.B) { From 3e17d6de9749b621453144652c8ff5706b00381d Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Fri, 1 Sep 2023 08:30:36 +0400 Subject: [PATCH 19/24] feat: add more prominent failure notice on slogtest error (#190) * feat: add more prominent failure notice on slogtest error Signed-off-by: Spike Curtis * reinstated Fatal logs calling tb.Fatal Signed-off-by: Spike Curtis --------- Signed-off-by: Spike Curtis --- sloggers/slogtest/t.go | 16 ++++++++++------ sloggers/slogtest/t_test.go | 2 +- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/sloggers/slogtest/t.go b/sloggers/slogtest/t.go index 9d81766..6923054 100644 --- a/sloggers/slogtest/t.go +++ b/sloggers/slogtest/t.go @@ -7,6 +7,7 @@ package slogtest // import "cdr.dev/slog/sloggers/slogtest" import ( "context" + "fmt" "log" "os" "strings" @@ -78,19 +79,22 @@ func (ts *testSink) LogEntry(ctx context.Context, ent slog.SinkEntry) { // The testing package logs to stdout and not stderr. entryhuman.Fmt(&sb, os.Stdout, ent) - s := sb.String() - switch ent.Level { case slog.LevelDebug, slog.LevelInfo, slog.LevelWarn: - ts.tb.Log(s) + ts.tb.Log(sb.String()) case slog.LevelError, slog.LevelCritical: if ts.opts.IgnoreErrors { - ts.tb.Log(s) + ts.tb.Log(sb.String()) } else { - ts.tb.Error(s) + sb.WriteString(fmt.Sprintf( + "\n *** slogtest: log detected at level %s; TEST FAILURE ***", + ent.Level, + )) + ts.tb.Error(sb.String()) } case slog.LevelFatal: - ts.tb.Fatal(s) + sb.WriteString("\n *** slogtest: FATAL log detected; TEST FAILURE ***") + ts.tb.Fatal(sb.String()) } } diff --git a/sloggers/slogtest/t_test.go b/sloggers/slogtest/t_test.go index d55fa88..9c1b88a 100644 --- a/sloggers/slogtest/t_test.go +++ b/sloggers/slogtest/t_test.go @@ -55,7 +55,7 @@ func TestCleanup(t *testing.T) { fn() } - // This shoud not log since the logger was cleaned up. + // This should not log since the logger was cleaned up. l.Info(bg, "hello") assert.Equal(t, "no logs", 0, tb.logs) } From f0c466fabe10641afdbcc629938df29f941b3d18 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 29 Sep 2023 22:36:52 +0300 Subject: [PATCH 20/24] fix: add additional severity field to stackdriver (#194) --- sloggers/slogstackdriver/slogstackdriver.go | 1 + sloggers/slogstackdriver/slogstackdriver_test.go | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sloggers/slogstackdriver/slogstackdriver.go b/sloggers/slogstackdriver/slogstackdriver.go index f9eed55..9772ed4 100644 --- a/sloggers/slogstackdriver/slogstackdriver.go +++ b/sloggers/slogstackdriver/slogstackdriver.go @@ -56,6 +56,7 @@ func (s stackdriverSink) LogEntry(ctx context.Context, ent slog.SinkEntry) { // https://cloud.google.com/stackdriver/docs/solutions/agents/ops-agent/configuration#special-fields e := slog.M( slog.F("logging.googleapis.com/severity", sev(ent.Level)), + slog.F("severity", sev(ent.Level)), slog.F("message", ent.Message), // Unfortunately, both of these fields are required. slog.F("timestampSeconds", ent.Time.Unix()), diff --git a/sloggers/slogstackdriver/slogstackdriver_test.go b/sloggers/slogstackdriver/slogstackdriver_test.go index ec58ba7..7a79985 100644 --- a/sloggers/slogstackdriver/slogstackdriver_test.go +++ b/sloggers/slogstackdriver/slogstackdriver_test.go @@ -43,7 +43,7 @@ func TestStackdriver(t *testing.T) { j := entryjson.Filter(b.String(), "timestampSeconds") j = entryjson.Filter(j, "timestampNanos") - exp := fmt.Sprintf(`{"logging.googleapis.com/severity":"ERROR","message":"line1\n\nline2","logging.googleapis.com/sourceLocation":{"file":"%v","line":40,"function":"cdr.dev/slog/sloggers/slogstackdriver_test.TestStackdriver"},"logging.googleapis.com/operation":{"producer":"meow"},"logging.googleapis.com/trace":"projects/%v/traces/%v","logging.googleapis.com/spanId":"%v","logging.googleapis.com/trace_sampled":%v,"wowow":"me\nyou"} + exp := fmt.Sprintf(`{"logging.googleapis.com/severity":"ERROR","severity":"ERROR","message":"line1\n\nline2","logging.googleapis.com/sourceLocation":{"file":"%v","line":40,"function":"cdr.dev/slog/sloggers/slogstackdriver_test.TestStackdriver"},"logging.googleapis.com/operation":{"producer":"meow"},"logging.googleapis.com/trace":"projects/%v/traces/%v","logging.googleapis.com/spanId":"%v","logging.googleapis.com/trace_sampled":%v,"wowow":"me\nyou"} `, slogstackdriverTestFile, projectID, span.SpanContext().TraceID(), span.SpanContext().SpanID(), span.SpanContext().IsSampled()) assert.Equal(t, "entry", exp, j) } From 20367d4aede690b72a0c43f847b7fc0645f94a92 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Fri, 26 Jan 2024 10:47:26 +0400 Subject: [PATCH 21/24] feat: ignore context.Canceled by default in slogtest (#207) * feat: ignore context.Canceled by default in slogtest Signed-off-by: Spike Curtis * code review suggestions Signed-off-by: Spike Curtis --------- Signed-off-by: Spike Curtis --- sloggers/slogtest/t.go | 39 +++++++++++++++++++++-- sloggers/slogtest/t_test.go | 63 +++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 3 deletions(-) diff --git a/sloggers/slogtest/t.go b/sloggers/slogtest/t.go index 6923054..df0225a 100644 --- a/sloggers/slogtest/t.go +++ b/sloggers/slogtest/t.go @@ -14,6 +14,8 @@ import ( "sync" "testing" + "golang.org/x/xerrors" + "cdr.dev/slog" "cdr.dev/slog/internal/entryhuman" "cdr.dev/slog/sloggers/sloghuman" @@ -36,13 +38,26 @@ type Options struct { // conditions exist when t.Log is called concurrently of a test exiting. Set // to true if you don't need this behavior. SkipCleanup bool + // IgnoredErrorIs causes the test logger not to error the test on Error + // if the SinkEntry contains one of the listed errors in its "error" Field. + // Errors are matched using xerrors.Is(). + // + // By default, context.Canceled and context.DeadlineExceeded are included, + // as these are nearly always benign in testing. Override to []error{} (zero + // length error slice) to disable the whitelist entirely. + IgnoredErrorIs []error } -// Make creates a Logger that writes logs to tb in a human readable format. +var DefaultIgnoredErrorIs = []error{context.Canceled, context.DeadlineExceeded} + +// Make creates a Logger that writes logs to tb in a human-readable format. func Make(tb testing.TB, opts *Options) slog.Logger { if opts == nil { opts = &Options{} } + if opts.IgnoredErrorIs == nil { + opts.IgnoredErrorIs = DefaultIgnoredErrorIs + } sink := &testSink{ tb: tb, @@ -66,7 +81,7 @@ type testSink struct { testDone bool } -func (ts *testSink) LogEntry(ctx context.Context, ent slog.SinkEntry) { +func (ts *testSink) LogEntry(_ context.Context, ent slog.SinkEntry) { ts.mu.RLock() defer ts.mu.RUnlock() @@ -83,7 +98,7 @@ func (ts *testSink) LogEntry(ctx context.Context, ent slog.SinkEntry) { case slog.LevelDebug, slog.LevelInfo, slog.LevelWarn: ts.tb.Log(sb.String()) case slog.LevelError, slog.LevelCritical: - if ts.opts.IgnoreErrors { + if ts.shouldIgnoreError(ent) { ts.tb.Log(sb.String()) } else { sb.WriteString(fmt.Sprintf( @@ -98,6 +113,24 @@ func (ts *testSink) LogEntry(ctx context.Context, ent slog.SinkEntry) { } } +func (ts *testSink) shouldIgnoreError(ent slog.SinkEntry) bool { + if ts.opts.IgnoreErrors { + return true + } + for _, f := range ent.Fields { + if f.Name == "error" { + if err, ok := f.Value.(error); ok { + for _, ig := range ts.opts.IgnoredErrorIs { + if xerrors.Is(err, ig) { + return true + } + } + } + } + } + return false +} + func (ts *testSink) Sync() {} var ctx = context.Background() diff --git a/sloggers/slogtest/t_test.go b/sloggers/slogtest/t_test.go index 9c1b88a..0637bc5 100644 --- a/sloggers/slogtest/t_test.go +++ b/sloggers/slogtest/t_test.go @@ -4,6 +4,9 @@ import ( "context" "testing" + "golang.org/x/xerrors" + + "cdr.dev/slog" "cdr.dev/slog/internal/assert" "cdr.dev/slog/sloggers/slogtest" ) @@ -15,6 +18,12 @@ func TestStateless(t *testing.T) { slogtest.Debug(tb, "hello") slogtest.Info(tb, "hello") + slogtest.Error(tb, "canceled", slog.Error(xerrors.Errorf("test %w:", context.Canceled))) + assert.Equal(t, "errors", 0, tb.errors) + + slogtest.Error(tb, "deadline", slog.Error(xerrors.Errorf("test %w:", context.DeadlineExceeded))) + assert.Equal(t, "errors", 0, tb.errors) + slogtest.Error(tb, "hello") assert.Equal(t, "errors", 1, tb.errors) @@ -45,6 +54,60 @@ func TestIgnoreErrors(t *testing.T) { l.Fatal(bg, "hello") } +func TestIgnoreErrorIs_Default(t *testing.T) { + t.Parallel() + + tb := &fakeTB{} + l := slogtest.Make(tb, nil) + + l.Error(bg, "canceled", slog.Error(xerrors.Errorf("test %w:", context.Canceled))) + assert.Equal(t, "errors", 0, tb.errors) + + l.Error(bg, "deadline", slog.Error(xerrors.Errorf("test %w:", context.DeadlineExceeded))) + assert.Equal(t, "errors", 0, tb.errors) + + l.Error(bg, "new", slog.Error(xerrors.New("test"))) + assert.Equal(t, "errors", 1, tb.errors) + + defer func() { + recover() + assert.Equal(t, "fatals", 1, tb.fatals) + }() + + l.Fatal(bg, "hello", slog.Error(xerrors.Errorf("fatal %w:", context.Canceled))) +} + +func TestIgnoreErrorIs_Explicit(t *testing.T) { + t.Parallel() + + tb := &fakeTB{} + ignored := xerrors.New("ignored") + notIgnored := xerrors.New("not ignored") + l := slogtest.Make(tb, &slogtest.Options{IgnoredErrorIs: []error{ignored}}) + + l.Error(bg, "ignored", slog.Error(xerrors.Errorf("test %w:", ignored))) + assert.Equal(t, "errors", 0, tb.errors) + + l.Error(bg, "not ignored", slog.Error(xerrors.Errorf("test %w:", notIgnored))) + assert.Equal(t, "errors", 1, tb.errors) + + l.Error(bg, "canceled", slog.Error(xerrors.Errorf("test %w:", context.Canceled))) + assert.Equal(t, "errors", 2, tb.errors) + + l.Error(bg, "deadline", slog.Error(xerrors.Errorf("test %w:", context.DeadlineExceeded))) + assert.Equal(t, "errors", 3, tb.errors) + + l.Error(bg, "new", slog.Error(xerrors.New("test"))) + assert.Equal(t, "errors", 4, tb.errors) + + defer func() { + recover() + assert.Equal(t, "fatals", 1, tb.fatals) + }() + + l.Fatal(bg, "hello", slog.Error(xerrors.Errorf("test %w:", ignored))) +} + func TestCleanup(t *testing.T) { t.Parallel() From 3e5cea5e4d6a8c8396f626a8a4989cc02aea4ed1 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Fri, 8 Nov 2024 08:14:28 +0200 Subject: [PATCH 22/24] ci: fix lint, fmt and upload artifacts (#218) * chore(.github): update actions/upload-artifacts --- .github/workflows/ci.yml | 2 +- ci/fmt.mk | 3 ++- ci/lint.mk | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a212ec..0b453e9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: env: COVERALLS_TOKEN: ${{ secrets.github_token }} - name: Upload coverage.html - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: coverage path: ci/out/coverage.html diff --git a/ci/fmt.mk b/ci/fmt.mk index 7f74874..5519ed6 100644 --- a/ci/fmt.mk +++ b/ci/fmt.mk @@ -13,7 +13,8 @@ modtidy: gen go mod tidy gofmt: gen - go run mvdan.cc/gofumpt@latest -w . + # gofumpt v0.7.0 requires Go 1.22 or later. + go run mvdan.cc/gofumpt@v0.6.0 -w . prettier: npx prettier --write --print-width=120 --no-semi --trailing-comma=all --loglevel=warn $$(git ls-files "*.yml") diff --git a/ci/lint.mk b/ci/lint.mk index 36da85b..e190817 100644 --- a/ci/lint.mk +++ b/ci/lint.mk @@ -4,4 +4,5 @@ govet: go vet ./... golint: - go run github.com/golangci/golangci-lint/cmd/golangci-lint@latest run . + # golangci-lint newer than v1.55.2 is not compatible with Go 1.20 when using go run. + go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.55.2 run . From 0ec81e6e67bb1fe88d4d068a6c7325f449008201 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Tue, 12 Nov 2024 08:18:20 +0400 Subject: [PATCH 23/24] feat: add IgnoreErrorFn to slogtest options (#217) Signed-off-by: Spike Curtis --- sloggers/slogtest/t.go | 35 ++++++++++++++++++++------ sloggers/slogtest/t_test.go | 49 +++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 8 deletions(-) diff --git a/sloggers/slogtest/t.go b/sloggers/slogtest/t.go index df0225a..b1fbc86 100644 --- a/sloggers/slogtest/t.go +++ b/sloggers/slogtest/t.go @@ -46,6 +46,13 @@ type Options struct { // as these are nearly always benign in testing. Override to []error{} (zero // length error slice) to disable the whitelist entirely. IgnoredErrorIs []error + // IgnoreErrorFn, if non-nil, defines a function that should return true if + // the given SinkEntry should not error the test on Error or Critical. The + // result of this function is logically ORed with ignore directives defined + // by IgnoreErrors and IgnoredErrorIs. To depend exclusively on + // IgnoreErrorFn, set IgnoreErrors=false and IgnoredErrorIs=[]error{} (zero + // length error slice). + IgnoreErrorFn func(slog.SinkEntry) bool } var DefaultIgnoredErrorIs = []error{context.Canceled, context.DeadlineExceeded} @@ -117,17 +124,16 @@ func (ts *testSink) shouldIgnoreError(ent slog.SinkEntry) bool { if ts.opts.IgnoreErrors { return true } - for _, f := range ent.Fields { - if f.Name == "error" { - if err, ok := f.Value.(error); ok { - for _, ig := range ts.opts.IgnoredErrorIs { - if xerrors.Is(err, ig) { - return true - } - } + if err, ok := FindFirstError(ent); ok { + for _, ig := range ts.opts.IgnoredErrorIs { + if xerrors.Is(err, ig) { + return true } } } + if ts.opts.IgnoreErrorFn != nil { + return ts.opts.IgnoreErrorFn(ent) + } return false } @@ -162,3 +168,16 @@ func Fatal(t testing.TB, msg string, fields ...any) { slog.Helper() l(t).Fatal(ctx, msg, fields...) } + +// FindFirstError finds the first slog.Field named "error" that contains an +// error value. +func FindFirstError(ent slog.SinkEntry) (err error, ok bool) { + for _, f := range ent.Fields { + if f.Name == "error" { + if err, ok = f.Value.(error); ok { + return err, true + } + } + } + return nil, false +} diff --git a/sloggers/slogtest/t_test.go b/sloggers/slogtest/t_test.go index 0637bc5..2aa09d5 100644 --- a/sloggers/slogtest/t_test.go +++ b/sloggers/slogtest/t_test.go @@ -2,6 +2,7 @@ package slogtest_test import ( "context" + "fmt" "testing" "golang.org/x/xerrors" @@ -108,6 +109,46 @@ func TestIgnoreErrorIs_Explicit(t *testing.T) { l.Fatal(bg, "hello", slog.Error(xerrors.Errorf("test %w:", ignored))) } +func TestIgnoreErrorFn(t *testing.T) { + t.Parallel() + + tb := &fakeTB{} + ignored := testCodedError{code: 777} + notIgnored := testCodedError{code: 911} + l := slogtest.Make(tb, &slogtest.Options{IgnoreErrorFn: func(ent slog.SinkEntry) bool { + err, ok := slogtest.FindFirstError(ent) + if !ok { + t.Error("did not contain an error") + return false + } + ce := testCodedError{} + if !xerrors.As(err, &ce) { + return false + } + return ce.code != 911 + }}) + + l.Error(bg, "ignored", slog.Error(xerrors.Errorf("test %w:", ignored))) + assert.Equal(t, "errors", 0, tb.errors) + + l.Error(bg, "not ignored", slog.Error(xerrors.Errorf("test %w:", notIgnored))) + assert.Equal(t, "errors", 1, tb.errors) + + // still ignored by default for IgnoredErrorIs + l.Error(bg, "canceled", slog.Error(xerrors.Errorf("test %w:", context.Canceled))) + assert.Equal(t, "errors", 1, tb.errors) + + l.Error(bg, "new", slog.Error(xerrors.New("test"))) + assert.Equal(t, "errors", 2, tb.errors) + + defer func() { + recover() + assert.Equal(t, "fatals", 1, tb.fatals) + }() + + l.Fatal(bg, "hello", slog.Error(xerrors.Errorf("test %w:", ignored))) +} + func TestCleanup(t *testing.T) { t.Parallel() @@ -163,3 +204,11 @@ func (tb *fakeTB) Fatal(v ...interface{}) { func (tb *fakeTB) Cleanup(fn func()) { tb.cleanups = append(tb.cleanups, fn) } + +type testCodedError struct { + code int +} + +func (e testCodedError) Error() string { + return fmt.Sprintf("code: %d", e.code) +} From 9df5e0a6c14572480711c6c06dd26ceabe32ad72 Mon Sep 17 00:00:00 2001 From: Ethan <39577870+ethanndickson@users.noreply.github.com> Date: Thu, 3 Jul 2025 17:42:22 +1000 Subject: [PATCH 24/24] fix!: handle `sql/driver.Valuer` types properly in `slogjson` (#219) Currently, if a field like `sql.NullInt32` has `Valid: False`, `sloghuman` will export it's value as ``, regardless of it's `String`. This is because it checks `(driver.Valuer).Value()`. However, `slogjson` currently sets the value to the json string of the raw struct: ```json { "fields": { "Code": "{Int32:0 Valid:false}", "ValidCode": "{Int32:12 Valid:true}" } } ``` This PR handles this case by first checking if the type implements `sql/driver.Valuer`. If `Valid` is `false` then a JSON `null` value is produced: ```json { "fields": { "Code": null, "ValidCode": 12 } } ``` This matches the behaviour of `sloghuman`. This is technically a breaking change, as these types are now `T | null` instead of `String`, where `T` is the corresponding JSON type of `sql.Null` --- map.go | 9 +++++++++ map_test.go | 6 +++--- sloggers/slogjson/slogjson_test.go | 29 ++++++++++++++++++++++++++++- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/map.go b/map.go index 636f4ee..cbf2991 100644 --- a/map.go +++ b/map.go @@ -2,6 +2,7 @@ package slog import ( "bytes" + "database/sql/driver" "encoding/json" "fmt" "reflect" @@ -70,6 +71,14 @@ func marshalList(rv reflect.Value) []byte { } func encode(v interface{}) []byte { + if vr, ok := v.(driver.Valuer); ok { + var err error + v, err = vr.Value() + if err != nil { + return encodeJSON(fmt.Sprintf("error calling Value: %v", err)) + } + } + switch v := v.(type) { case json.Marshaler: return encodeJSON(v) diff --git a/map_test.go b/map_test.go index fce13b5..c89adf0 100644 --- a/map_test.go +++ b/map_test.go @@ -62,12 +62,12 @@ func TestMap(t *testing.T) { { "msg": "wrap1", "fun": "cdr.dev/slog_test.TestMap.func2", - "loc": "`+mapTestFile+`:41" + "loc": "`+mapTestFile+`:41" }, { "msg": "wrap2", "fun": "cdr.dev/slog_test.TestMap.func2", - "loc": "`+mapTestFile+`:42" + "loc": "`+mapTestFile+`:42" }, "EOF" ], @@ -93,7 +93,7 @@ func TestMap(t *testing.T) { { "msg": "failed to marshal to JSON", "fun": "cdr.dev/slog.encodeJSON", - "loc": "`+mapTestFile+`:131" + "loc": "`+mapTestFile+`:140" }, "json: error calling MarshalJSON for type slog_test.complexJSON: json: unsupported type: complex128" ], diff --git a/sloggers/slogjson/slogjson_test.go b/sloggers/slogjson/slogjson_test.go index 79a46e7..cdbffee 100644 --- a/sloggers/slogjson/slogjson_test.go +++ b/sloggers/slogjson/slogjson_test.go @@ -3,6 +3,7 @@ package slogjson_test import ( "bytes" "context" + "database/sql" "fmt" "runtime" "testing" @@ -33,7 +34,33 @@ func TestMake(t *testing.T) { l.Error(ctx, "line1\n\nline2", slog.F("wowow", "me\nyou")) j := entryjson.Filter(b.String(), "ts") - exp := fmt.Sprintf(`{"level":"ERROR","msg":"line1\n\nline2","caller":"%v:33","func":"cdr.dev/slog/sloggers/slogjson_test.TestMake","logger_names":["named"],"trace":"%v","span":"%v","fields":{"wowow":"me\nyou"}} + exp := fmt.Sprintf(`{"level":"ERROR","msg":"line1\n\nline2","caller":"%v:34","func":"cdr.dev/slog/sloggers/slogjson_test.TestMake","logger_names":["named"],"trace":"%v","span":"%v","fields":{"wowow":"me\nyou"}} `, slogjsonTestFile, span.SpanContext().TraceID().String(), span.SpanContext().SpanID().String()) assert.Equal(t, "entry", exp, j) } + +func TestNoDriverValue(t *testing.T) { + t.Parallel() + + b := &bytes.Buffer{} + l := slog.Make(slogjson.Sink(b)) + l = l.Named("named") + validField := sql.NullString{ + String: "cat", + Valid: true, + } + invalidField := sql.NullString{ + String: "dog", + Valid: false, + } + validInt := sql.NullInt64{ + Int64: 42, + Valid: true, + } + l.Error(bg, "error!", slog.F("inval", invalidField), slog.F("val", validField), slog.F("int", validInt)) + + j := entryjson.Filter(b.String(), "ts") + exp := fmt.Sprintf(`{"level":"ERROR","msg":"error!","caller":"%v:60","func":"cdr.dev/slog/sloggers/slogjson_test.TestNoDriverValue","logger_names":["named"],"fields":{"inval":null,"val":"cat","int":42}} +`, slogjsonTestFile) + assert.Equal(t, "entry", exp, j) +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy