mirror of https://github.com/knative/client.git
[main] Upgrade to latest dependencies (#1852)
* upgrade to latest dependencies
bumping go.uber.org/zap a55bdc3...56468e7:
> 56468e7 Release v1.25.0
> 249507a zap.Any: Reduce stack size with generics (# 1310)
> 50b2db4 zap.Any add benchmarks
> a0674c8 Add direct coverage to zap.Any (# 1309)
> 1310691 Table test TestFieldConstructors
> 382e251 Swap expected and got fields (# 1282)
> 24b7977 Add Name() to Logger (# 1273)
> 1155ed3 Introduce Str + Strs generic string helpers (# 1281)
> 4451b47 exp: Update slog, adjust for changes (# 1276)
> 845ca51 internal: Add and use a generic pool instead of using sync.Pool directly (# 1262)
> 42b7ef0 slog: Ignore frames with a zero PC (# 1258)
> 05c4b6c Remove dependency on github.com/pkg/errors (# 1255)
> d1a1923 Minimize permissions on CI workflows (# 1257)
> 384e782 Use sync/atomic, drop external atomics (# 1253)
> 740fda7 TestLevelFlag: Don't print to stderr (# 1254)
> f2f1f41 [Feature] Add experiment `zapslog` package to integrate with slog (# 1246)
> 54862f5 benchmark: add slog (# 1245)
> 85c4932 Add govulncheck as a CI step (# 1239)
> f4ba5f5 make: Switch from golint to revive (# 1238)
> 8310f89 chore: update bench package versions and results (# 1207)
> 8d89127 Bump actions/checkout from 2 to 3 (# 1237)
> bc64796 doc: New{Production,Development}Encoder{,Config} (# 1234)
> 692ec13 ci: Set up dependabot for GH actions and tools (# 1236)
> 7d6a9af ci: Test with Go 1.19 and 1.20 (# 1235)
> d4a1083 doc(SugaredLogger): Document print, printf, and println methods (# 1233)
> b32f3c5 Update Snyk vulnerable modules (# 1227)
> 53fdb6f Reverse comparison for readability (# 1228)
> 077b03e Use iota like a original from grpc-go (# 1220)
bumping knative.dev/serving e9425f8...eaff0b3:
> eaff0b3 upgrade to latest dependencies (# 14290)
> 587de3d Update net-kourier nightly (# 14286)
> 21264fc Update net-contour nightly (# 14284)
> a9b48be Deprecate calling kubetest2 via kntest (# 13329)
> 397cfde Update net-istio nightly (# 14285)
bumping knative.dev/eventing 29ac3ee...a2e2aa3:
> a2e2aa3 Eventing TLS: Test SinkBinding with Broker as sink (# 7172)
> d8a2ad5 change the deprecated string (# 7179)
> 0e88db1 Switch to trigger.WithNewFilters() to set trigger filter (# 7188)
> 9d2bcef Add kind e2e tests for Kubernetes v1.27.3 (# 7139)
> 2b02cb4 Add OIDC Authentication feature flag (# 7183)
bumping github.com/hashicorp/golang-lru 14eae34...a032ef5:
> a032ef5 Update README for v1.0.2
> bdf35e3 Remove deprecated linters
> bc1608d Update other tests to get rid of math/rand
> f2408b3 Update test to remove bad rand usage
> fa11c6b Update github workflow
> 6da3f98 Update MPL 2.0 LICENSE (# 110)
> d4900dc fix onEvictedCB bug (# 84)
> 003b81b Update go doc url (# 93)
> 80c9821 rework lru's external registered callback invocation to avoid concurr… (# 80)
> eb52994 Code quality improvements (# 67)
bumping go.uber.org/multierr 10aaa3c...8767aa9:
> 8767aa9 Prepare release v1.10 (# 74)
> 4504ef7 README: Add Features section (# 73)
> 2fd451d Drop external atomic dependency (# 72)
> 7876a02 Remove unused glide.yaml (# 71)
> 55bc553 Support Go 1.20 Unwrap() []error (# 69)
> 39ca40c Prepare release v1.9.0 (# 68)
> 4459990 Add a shorthand for AppendInvoke (# 65)
> 80b07a7 Document named return constraint for defer (# 63)
> 492b792 Test and lint against Go 1.19 (# 62)
> aa8f15f Upgrade to yaml.v3 3.0.1 (# 60)
> f46d400 Use append instead of copy to clone slices (# 58)
> 6fede5c CI: Test against Go 1.17/1.18 (# 57)
bumping google.golang.org/api 113082d...85e7e70:
> 85e7e70 chore(main): release 0.138.0 (# 2116)
> 9b75278 feat(all): auto-regenerate discovery clients (# 2119)
> 40ea606 feat(all): auto-regenerate discovery clients (# 2118)
> 1770219 feat(all): auto-regenerate discovery clients (# 2115)
> c631c0a chore(main): release 0.137.0 (# 2107)
> caea956 feat: ok to use S2A with override endpoint (# 2114)
> 142ffeb feat(all): auto-regenerate discovery clients (# 2113)
> f7f1c7b feat(all): auto-regenerate discovery clients (# 2112)
> 0cc62ab feat(all): auto-regenerate discovery clients (# 2111)
> 4d775db feat(all): auto-regenerate discovery clients (# 2110)
> 6d29bab chore(all): update module github.com/google/s2a-go to v0.1.5 (# 2109)
> 80485e0 feat(all): auto-regenerate discovery clients (# 2108)
> 3f3ed3d feat(all): auto-regenerate discovery clients (# 2106)
bumping knative.dev/networking 4bfcc9f...1d7920d:
> 1d7920d upgrade to latest dependencies (# 845)
bumping knative.dev/hack 044c02b...9cc05a3:
> 9cc05a3 Deprecate calling kubetest2 via kntest (# 230)
bumping knative.dev/client-pkg 38d2dc0...5abd129:
> 5abd129 Update community files (# 116)
bumping knative.dev/pkg 4f651e0...81e4ee1:
> 81e4ee1 Bump go.uber.org/zap from 1.24.0 to 1.25.0 (# 2800)
> 2aafe0e Bump cloud.google.com/go/storage from 1.31.0 to 1.32.0 (# 2801)
> 2ad39e9 Bump github.com/hashicorp/golang-lru from 0.5.4 to 1.0.2 (# 2804)
> d36cc59 Bump google.golang.org/api from 0.136.0 to 0.138.0 (# 2802)
> 35b0890 Bump go.uber.org/automaxprocs from 1.4.0 to 1.5.3 (# 2803)
> 93a9858 upgrade to latest dependencies (# 2799)
Signed-off-by: Knative Automation <automation@knative.team>
* Fix tls domain test
---------
Signed-off-by: Knative Automation <automation@knative.team>
Co-authored-by: David Simansky <dsimansk@redhat.com>
This commit is contained in:
parent
a9ee31fbb7
commit
62d2cbffa0
20
go.mod
20
go.mod
|
|
@ -4,7 +4,7 @@ go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/google/go-cmp v0.5.9
|
github.com/google/go-cmp v0.5.9
|
||||||
github.com/hashicorp/golang-lru v0.5.4
|
github.com/hashicorp/golang-lru v1.0.2
|
||||||
github.com/hashicorp/hcl v1.0.0
|
github.com/hashicorp/hcl v1.0.0
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/spf13/afero v1.9.2 // indirect
|
github.com/spf13/afero v1.9.2 // indirect
|
||||||
|
|
@ -20,12 +20,12 @@ require (
|
||||||
k8s.io/cli-runtime v0.25.2
|
k8s.io/cli-runtime v0.25.2
|
||||||
k8s.io/client-go v0.26.5
|
k8s.io/client-go v0.26.5
|
||||||
k8s.io/code-generator v0.26.5
|
k8s.io/code-generator v0.26.5
|
||||||
knative.dev/client-pkg v0.0.0-20230809014238-38d2dc0dd50a
|
knative.dev/client-pkg v0.0.0-20230815131440-5abd12981b4b
|
||||||
knative.dev/eventing v0.38.1-0.20230815095940-29ac3eee64a4
|
knative.dev/eventing v0.38.1-0.20230822134255-a2e2aa3d515d
|
||||||
knative.dev/hack v0.0.0-20230815012940-044c02b7a447
|
knative.dev/hack v0.0.0-20230818155117-9cc05a31e8c0
|
||||||
knative.dev/networking v0.0.0-20230817140742-4bfcc9fb6012
|
knative.dev/networking v0.0.0-20230822003854-1d7920d27b9e
|
||||||
knative.dev/pkg v0.0.0-20230815132840-4f651e092853
|
knative.dev/pkg v0.0.0-20230821102121-81e4ee140363
|
||||||
knative.dev/serving v0.38.1-0.20230818202718-e9425f8d5260
|
knative.dev/serving v0.38.1-0.20230823024257-eaff0b39b99e
|
||||||
sigs.k8s.io/yaml v1.3.0
|
sigs.k8s.io/yaml v1.3.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -102,8 +102,8 @@ require (
|
||||||
go.opencensus.io v0.24.0 // indirect
|
go.opencensus.io v0.24.0 // indirect
|
||||||
go.starlark.net v0.0.0-20220817180228-f738f5508c12 // indirect
|
go.starlark.net v0.0.0-20220817180228-f738f5508c12 // indirect
|
||||||
go.uber.org/atomic v1.10.0 // indirect
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
go.uber.org/multierr v1.8.0 // indirect
|
go.uber.org/multierr v1.10.0 // indirect
|
||||||
go.uber.org/zap v1.24.0 // indirect
|
go.uber.org/zap v1.25.0 // indirect
|
||||||
golang.org/x/net v0.14.0 // indirect
|
golang.org/x/net v0.14.0 // indirect
|
||||||
golang.org/x/oauth2 v0.11.0 // indirect
|
golang.org/x/oauth2 v0.11.0 // indirect
|
||||||
golang.org/x/sync v0.3.0 // indirect
|
golang.org/x/sync v0.3.0 // indirect
|
||||||
|
|
@ -112,7 +112,7 @@ require (
|
||||||
golang.org/x/time v0.3.0 // indirect
|
golang.org/x/time v0.3.0 // indirect
|
||||||
golang.org/x/tools v0.12.0 // indirect
|
golang.org/x/tools v0.12.0 // indirect
|
||||||
gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect
|
gomodules.xyz/jsonpatch/v2 v2.3.0 // indirect
|
||||||
google.golang.org/api v0.136.0 // indirect
|
google.golang.org/api v0.138.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect
|
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 // indirect
|
||||||
|
|
|
||||||
44
go.sum
44
go.sum
|
|
@ -52,7 +52,7 @@ github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8V
|
||||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves=
|
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves=
|
||||||
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
|
github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
|
||||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
|
@ -224,8 +224,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjd
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3/go.mod h1:o//XUCC/F+yRGJoPO/VU0GSB0f8Nhgmxx0VIRUvaC0w=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
||||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
|
|
@ -415,16 +415,15 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe
|
||||||
go.starlark.net v0.0.0-20220817180228-f738f5508c12 h1:xOBJXWGEDwU5xSDxH6macxO11Us0AH2fTa9rmsbbF7g=
|
go.starlark.net v0.0.0-20220817180228-f738f5508c12 h1:xOBJXWGEDwU5xSDxH6macxO11Us0AH2fTa9rmsbbF7g=
|
||||||
go.starlark.net v0.0.0-20220817180228-f738f5508c12/go.mod h1:VZcBMdr3cT3PnBoWunTabuSEXwVAH+ZJ5zxfs3AdASk=
|
go.starlark.net v0.0.0-20220817180228-f738f5508c12/go.mod h1:VZcBMdr3cT3PnBoWunTabuSEXwVAH+ZJ5zxfs3AdASk=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
|
||||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
|
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||||
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
|
||||||
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
|
@ -687,8 +686,8 @@ google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz513
|
||||||
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
|
||||||
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
|
||||||
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
|
||||||
google.golang.org/api v0.136.0 h1:e/6enzUE1s4tGPa6Q3ZYShKTtvRc+1Jq0rrafhppmOs=
|
google.golang.org/api v0.138.0 h1:K/tVp05MxNVbHShRw9m7e9VJGdagNeTdMzqPH7AUqr0=
|
||||||
google.golang.org/api v0.136.0/go.mod h1:XtJfF+V2zgUxelOn5Zs3kECtluMxneJG8ZxUTlLNTPA=
|
google.golang.org/api v0.138.0/go.mod h1:4xyob8CxC+0GChNBvEUAk8VBKNvYOTWM9T3v3UfRxuY=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
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/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
|
@ -801,7 +800,6 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
@ -835,18 +833,18 @@ k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+O
|
||||||
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
|
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
|
||||||
k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2 h1:GfD9OzL11kvZN5iArC6oTS7RTj7oJOIfnislxYlqTj8=
|
k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2 h1:GfD9OzL11kvZN5iArC6oTS7RTj7oJOIfnislxYlqTj8=
|
||||||
k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
k8s.io/utils v0.0.0-20221108210102-8e77b1f39fe2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||||
knative.dev/client-pkg v0.0.0-20230809014238-38d2dc0dd50a h1:h+8sIUP03mCGO8vYI4qwT1GD88824n73EpZS8IsihXw=
|
knative.dev/client-pkg v0.0.0-20230815131440-5abd12981b4b h1:Ln3mDUER89kC4sYHkCpoZVcwthGlMwjekQi2IdMH4vU=
|
||||||
knative.dev/client-pkg v0.0.0-20230809014238-38d2dc0dd50a/go.mod h1:GRVZm1rKOy0lpPBGRM1ugK5joDbhXFEvULINHqPoA9U=
|
knative.dev/client-pkg v0.0.0-20230815131440-5abd12981b4b/go.mod h1:GRVZm1rKOy0lpPBGRM1ugK5joDbhXFEvULINHqPoA9U=
|
||||||
knative.dev/eventing v0.38.1-0.20230815095940-29ac3eee64a4 h1:619xUZrwrv3xuterMgF8qKXLTJm1MosKwuTLcG5HTOk=
|
knative.dev/eventing v0.38.1-0.20230822134255-a2e2aa3d515d h1:K8EcKbY3POUZ+D7uekPUqYY7m+Ci3nkYu1+SqpYiwdY=
|
||||||
knative.dev/eventing v0.38.1-0.20230815095940-29ac3eee64a4/go.mod h1:InEIckt+XICxXXYy2P4kqEJ4nMDXqI1iCUZ84vGDRbM=
|
knative.dev/eventing v0.38.1-0.20230822134255-a2e2aa3d515d/go.mod h1:InEIckt+XICxXXYy2P4kqEJ4nMDXqI1iCUZ84vGDRbM=
|
||||||
knative.dev/hack v0.0.0-20230815012940-044c02b7a447 h1:Lr4O/WEyZHuUBFbqATYdQlfLXvhPUCluF4zlgRi59T4=
|
knative.dev/hack v0.0.0-20230818155117-9cc05a31e8c0 h1:n9YEGYuoj31pAkhGlNL+xTQAeXKYTLeMmIZLWA9fAeo=
|
||||||
knative.dev/hack v0.0.0-20230815012940-044c02b7a447/go.mod h1:yk2OjGDsbEnQjfxdm0/HJKS2WqTLEFg/N6nUs6Rqx3Q=
|
knative.dev/hack v0.0.0-20230818155117-9cc05a31e8c0/go.mod h1:yk2OjGDsbEnQjfxdm0/HJKS2WqTLEFg/N6nUs6Rqx3Q=
|
||||||
knative.dev/networking v0.0.0-20230817140742-4bfcc9fb6012 h1:eaeZPgJzsJMnJaekbG8TYAfF/PUX8Xmdb8Oqnb+QO1k=
|
knative.dev/networking v0.0.0-20230822003854-1d7920d27b9e h1:9CcYOXJKJSiZ5aeNm0AJZ1DjOlisadZhMSa/O/hOSmE=
|
||||||
knative.dev/networking v0.0.0-20230817140742-4bfcc9fb6012/go.mod h1:iGxfnvUJ3gGqtKnoOXhLzNCZeGxVnH4xdClYuh5vB4o=
|
knative.dev/networking v0.0.0-20230822003854-1d7920d27b9e/go.mod h1:1voQlQD0tuot6U3Kldw+uch33mK2LV85fi3MfbV0CP8=
|
||||||
knative.dev/pkg v0.0.0-20230815132840-4f651e092853 h1:OyAYpXLa/jQWClFxRegCccGySyX2/1BVRtKaAWRE/xM=
|
knative.dev/pkg v0.0.0-20230821102121-81e4ee140363 h1:TI2hMwTM5Bl+yaWu1gN5bXAHSvc+FtH9cqm3NzmDBtY=
|
||||||
knative.dev/pkg v0.0.0-20230815132840-4f651e092853/go.mod h1:Y5Tis5nMoapB9iTZywW20Qnv/7LBahrtHz9Sm6+l3LE=
|
knative.dev/pkg v0.0.0-20230821102121-81e4ee140363/go.mod h1:dA3TdhFTRm4KmmpvfknpGV43SbGNFkLHySjC8/+NczM=
|
||||||
knative.dev/serving v0.38.1-0.20230818202718-e9425f8d5260 h1:3lhCzzCQp+KHS5Ms+9YUw64iiZy0VSxWTmXNXdY4cZE=
|
knative.dev/serving v0.38.1-0.20230823024257-eaff0b39b99e h1:LbHIIoOPcHXDwoJO/5OYqBx46ChN5heEujHiJK71GBc=
|
||||||
knative.dev/serving v0.38.1-0.20230818202718-e9425f8d5260/go.mod h1:NV6PfPFIjLoDdm9sgo1ccvWG6owBZeQld/bNxWt/8D0=
|
knative.dev/serving v0.38.1-0.20230823024257-eaff0b39b99e/go.mod h1:/q/HksDFhDiPdwOiyFdDE464YF+GjOYL22x7q57NPB0=
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,16 @@
|
||||||
package e2e
|
package e2e
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/elliptic"
|
||||||
|
"crypto/rand"
|
||||||
|
"crypto/x509"
|
||||||
|
"crypto/x509/pkix"
|
||||||
|
"encoding/pem"
|
||||||
|
"math/big"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -63,6 +73,20 @@ func TestDomain(t *testing.T) {
|
||||||
t.Log("delete domain")
|
t.Log("delete domain")
|
||||||
domainDelete(r, domainName)
|
domainDelete(r, domainName)
|
||||||
|
|
||||||
|
tempDir := t.TempDir()
|
||||||
|
defer os.Remove(tempDir)
|
||||||
|
|
||||||
|
cert, key := makeCertificateForDomain(t, "newdomain.com")
|
||||||
|
|
||||||
|
err = os.WriteFile(filepath.Join(tempDir, "cert"), cert, test.FileModeReadWrite)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
err = os.WriteFile(filepath.Join(tempDir, "key"), key, test.FileModeReadWrite)
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
|
kubectl = test.NewKubectl(it.Namespace())
|
||||||
|
_, err = kubectl.Run("create", "secret", "tls", "tls-secret", "--cert="+filepath.Join(tempDir, "cert"), "--key="+filepath.Join(tempDir, "key"))
|
||||||
|
assert.NilError(t, err)
|
||||||
|
|
||||||
t.Log("create domain with TLS")
|
t.Log("create domain with TLS")
|
||||||
domainCreateWithTls(r, "newdomain.com", "hello", "tls-secret")
|
domainCreateWithTls(r, "newdomain.com", "hello", "tls-secret")
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
|
@ -128,3 +152,44 @@ func domainDescribe(r *test.KnRunResultCollector, domainName string, tls bool) {
|
||||||
}
|
}
|
||||||
assert.Assert(r.T(), util.ContainsAll(out.Stdout, "Name", "Namespace", "URL", "Service", url))
|
assert.Assert(r.T(), util.ContainsAll(out.Stdout, "Name", "Namespace", "URL", "Service", url))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makeCertificateForDomain(t *testing.T, domainName string) (cert []byte, key []byte) {
|
||||||
|
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||||
|
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to generate serial number: %v", err)
|
||||||
|
}
|
||||||
|
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to generate private key: %v", err)
|
||||||
|
}
|
||||||
|
public := &priv.PublicKey
|
||||||
|
now := time.Now()
|
||||||
|
template := x509.Certificate{
|
||||||
|
SerialNumber: serialNumber,
|
||||||
|
Subject: pkix.Name{
|
||||||
|
Organization: []string{"Acme Co"},
|
||||||
|
},
|
||||||
|
NotBefore: now,
|
||||||
|
NotAfter: now.Add(time.Hour * 12),
|
||||||
|
|
||||||
|
KeyUsage: x509.KeyUsageDigitalSignature,
|
||||||
|
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||||
|
BasicConstraintsValid: true,
|
||||||
|
DNSNames: []string{domainName},
|
||||||
|
}
|
||||||
|
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, public, priv)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to create certificate: %v", err)
|
||||||
|
}
|
||||||
|
var certOut bytes.Buffer
|
||||||
|
pem.Encode(&certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
||||||
|
|
||||||
|
privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to marshal private key: %v", err)
|
||||||
|
}
|
||||||
|
var keyOut bytes.Buffer
|
||||||
|
pem.Encode(&keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes})
|
||||||
|
return certOut.Bytes(), keyOut.Bytes()
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- megacheck
|
||||||
|
- revive
|
||||||
|
- govet
|
||||||
|
- unconvert
|
||||||
|
- megacheck
|
||||||
|
- gas
|
||||||
|
- gocyclo
|
||||||
|
- dupl
|
||||||
|
- misspell
|
||||||
|
- unparam
|
||||||
|
- unused
|
||||||
|
- typecheck
|
||||||
|
- ineffassign
|
||||||
|
- stylecheck
|
||||||
|
- exportloopref
|
||||||
|
- gocritic
|
||||||
|
- nakedret
|
||||||
|
- gosimple
|
||||||
|
- prealloc
|
||||||
|
fast: false
|
||||||
|
disable-all: true
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-rules:
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- dupl
|
||||||
|
exclude-use-default: false
|
||||||
|
|
@ -44,7 +44,7 @@ func New2Q(size int) (*TwoQueueCache, error) {
|
||||||
|
|
||||||
// New2QParams creates a new TwoQueueCache using the provided
|
// New2QParams creates a new TwoQueueCache using the provided
|
||||||
// parameter values.
|
// parameter values.
|
||||||
func New2QParams(size int, recentRatio float64, ghostRatio float64) (*TwoQueueCache, error) {
|
func New2QParams(size int, recentRatio, ghostRatio float64) (*TwoQueueCache, error) {
|
||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
return nil, fmt.Errorf("invalid size")
|
return nil, fmt.Errorf("invalid size")
|
||||||
}
|
}
|
||||||
|
|
@ -138,7 +138,6 @@ func (c *TwoQueueCache) Add(key, value interface{}) {
|
||||||
// Add to the recently seen list
|
// Add to the recently seen list
|
||||||
c.ensureSpace(false)
|
c.ensureSpace(false)
|
||||||
c.recent.Add(key, value)
|
c.recent.Add(key, value)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensureSpace is used to ensure we have space in the cache
|
// ensureSpace is used to ensure we have space in the cache
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
Copyright (c) 2014 HashiCorp, Inc.
|
||||||
|
|
||||||
Mozilla Public License, version 2.0
|
Mozilla Public License, version 2.0
|
||||||
|
|
||||||
1. Definitions
|
1. Definitions
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,7 @@
|
||||||
golang-lru
|
golang-lru
|
||||||
==========
|
==========
|
||||||
|
|
||||||
This provides the `lru` package which implements a fixed-size
|
Please upgrade to github.com/hashicorp/golang-lru/v2 for all new code as v1 will
|
||||||
thread safe LRU cache. It is based on the cache in Groupcache.
|
not be updated anymore. The v2 version supports generics and is faster; old code
|
||||||
|
can specify a specific tag, e.g. github.com/hashicorp/golang-lru/v1.0.2 for
|
||||||
Documentation
|
backwards compatibility.
|
||||||
=============
|
|
||||||
|
|
||||||
Full docs are available on [Godoc](http://godoc.org/github.com/hashicorp/golang-lru)
|
|
||||||
|
|
||||||
Example
|
|
||||||
=======
|
|
||||||
|
|
||||||
Using the LRU is very simple:
|
|
||||||
|
|
||||||
```go
|
|
||||||
l, _ := New(128)
|
|
||||||
for i := 0; i < 256; i++ {
|
|
||||||
l.Add(i, nil)
|
|
||||||
}
|
|
||||||
if l.Len() != 128 {
|
|
||||||
panic(fmt.Sprintf("bad len: %v", l.Len()))
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,6 @@ func (c *ARCCache) Add(key, value interface{}) {
|
||||||
|
|
||||||
// Add to the recently seen list
|
// Add to the recently seen list
|
||||||
c.t1.Add(key, value)
|
c.t1.Add(key, value)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace is used to adaptively evict from either T1 or T2
|
// replace is used to adaptively evict from either T1 or T2
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,17 @@ import (
|
||||||
"github.com/hashicorp/golang-lru/simplelru"
|
"github.com/hashicorp/golang-lru/simplelru"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultEvictedBufferSize defines the default buffer size to store evicted key/val
|
||||||
|
DefaultEvictedBufferSize = 16
|
||||||
|
)
|
||||||
|
|
||||||
// Cache is a thread-safe fixed size LRU cache.
|
// Cache is a thread-safe fixed size LRU cache.
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
lru simplelru.LRUCache
|
lru *simplelru.LRU
|
||||||
lock sync.RWMutex
|
evictedKeys, evictedVals []interface{}
|
||||||
|
onEvictedCB func(k, v interface{})
|
||||||
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates an LRU of the given size.
|
// New creates an LRU of the given size.
|
||||||
|
|
@ -19,30 +26,63 @@ func New(size int) (*Cache, error) {
|
||||||
|
|
||||||
// NewWithEvict constructs a fixed size cache with the given eviction
|
// NewWithEvict constructs a fixed size cache with the given eviction
|
||||||
// callback.
|
// callback.
|
||||||
func NewWithEvict(size int, onEvicted func(key interface{}, value interface{})) (*Cache, error) {
|
func NewWithEvict(size int, onEvicted func(key, value interface{})) (c *Cache, err error) {
|
||||||
lru, err := simplelru.NewLRU(size, simplelru.EvictCallback(onEvicted))
|
// create a cache with default settings
|
||||||
if err != nil {
|
c = &Cache{
|
||||||
return nil, err
|
onEvictedCB: onEvicted,
|
||||||
}
|
}
|
||||||
c := &Cache{
|
if onEvicted != nil {
|
||||||
lru: lru,
|
c.initEvictBuffers()
|
||||||
|
onEvicted = c.onEvicted
|
||||||
}
|
}
|
||||||
return c, nil
|
c.lru, err = simplelru.NewLRU(size, onEvicted)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cache) initEvictBuffers() {
|
||||||
|
c.evictedKeys = make([]interface{}, 0, DefaultEvictedBufferSize)
|
||||||
|
c.evictedVals = make([]interface{}, 0, DefaultEvictedBufferSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// onEvicted save evicted key/val and sent in externally registered callback
|
||||||
|
// outside of critical section
|
||||||
|
func (c *Cache) onEvicted(k, v interface{}) {
|
||||||
|
c.evictedKeys = append(c.evictedKeys, k)
|
||||||
|
c.evictedVals = append(c.evictedVals, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Purge is used to completely clear the cache.
|
// Purge is used to completely clear the cache.
|
||||||
func (c *Cache) Purge() {
|
func (c *Cache) Purge() {
|
||||||
|
var ks, vs []interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
c.lru.Purge()
|
c.lru.Purge()
|
||||||
|
if c.onEvictedCB != nil && len(c.evictedKeys) > 0 {
|
||||||
|
ks, vs = c.evictedKeys, c.evictedVals
|
||||||
|
c.initEvictBuffers()
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
// invoke callback outside of critical section
|
||||||
|
if c.onEvictedCB != nil {
|
||||||
|
for i := 0; i < len(ks); i++ {
|
||||||
|
c.onEvictedCB(ks[i], vs[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add adds a value to the cache. Returns true if an eviction occurred.
|
// Add adds a value to the cache. Returns true if an eviction occurred.
|
||||||
func (c *Cache) Add(key, value interface{}) (evicted bool) {
|
func (c *Cache) Add(key, value interface{}) (evicted bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
evicted = c.lru.Add(key, value)
|
evicted = c.lru.Add(key, value)
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
return evicted
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get looks up a key's value from the cache.
|
// Get looks up a key's value from the cache.
|
||||||
|
|
@ -75,13 +115,21 @@ func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) {
|
||||||
// recent-ness or deleting it for being stale, and if not, adds the value.
|
// recent-ness or deleting it for being stale, and if not, adds the value.
|
||||||
// Returns whether found and whether an eviction occurred.
|
// Returns whether found and whether an eviction occurred.
|
||||||
func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
|
func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
if c.lru.Contains(key) {
|
if c.lru.Contains(key) {
|
||||||
|
c.lock.Unlock()
|
||||||
return true, false
|
return true, false
|
||||||
}
|
}
|
||||||
evicted = c.lru.Add(key, value)
|
evicted = c.lru.Add(key, value)
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return false, evicted
|
return false, evicted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,47 +137,80 @@ func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
|
||||||
// recent-ness or deleting it for being stale, and if not, adds the value.
|
// recent-ness or deleting it for being stale, and if not, adds the value.
|
||||||
// Returns whether found and whether an eviction occurred.
|
// Returns whether found and whether an eviction occurred.
|
||||||
func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evicted bool) {
|
func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evicted bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
previous, ok = c.lru.Peek(key)
|
previous, ok = c.lru.Peek(key)
|
||||||
if ok {
|
if ok {
|
||||||
|
c.lock.Unlock()
|
||||||
return previous, true, false
|
return previous, true, false
|
||||||
}
|
}
|
||||||
|
|
||||||
evicted = c.lru.Add(key, value)
|
evicted = c.lru.Add(key, value)
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return nil, false, evicted
|
return nil, false, evicted
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes the provided key from the cache.
|
// Remove removes the provided key from the cache.
|
||||||
func (c *Cache) Remove(key interface{}) (present bool) {
|
func (c *Cache) Remove(key interface{}) (present bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
present = c.lru.Remove(key)
|
present = c.lru.Remove(key)
|
||||||
|
if c.onEvictedCB != nil && present {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && present {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize changes the cache size.
|
// Resize changes the cache size.
|
||||||
func (c *Cache) Resize(size int) (evicted int) {
|
func (c *Cache) Resize(size int) (evicted int) {
|
||||||
|
var ks, vs []interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
evicted = c.lru.Resize(size)
|
evicted = c.lru.Resize(size)
|
||||||
|
if c.onEvictedCB != nil && evicted > 0 {
|
||||||
|
ks, vs = c.evictedKeys, c.evictedVals
|
||||||
|
c.initEvictBuffers()
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && evicted > 0 {
|
||||||
|
for i := 0; i < len(ks); i++ {
|
||||||
|
c.onEvictedCB(ks[i], vs[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
return evicted
|
return evicted
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveOldest removes the oldest item from the cache.
|
// RemoveOldest removes the oldest item from the cache.
|
||||||
func (c *Cache) RemoveOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *Cache) RemoveOldest() (key, value interface{}, ok bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
key, value, ok = c.lru.RemoveOldest()
|
key, value, ok = c.lru.RemoveOldest()
|
||||||
|
if c.onEvictedCB != nil && ok {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && ok {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOldest returns the oldest entry
|
// GetOldest returns the oldest entry
|
||||||
func (c *Cache) GetOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *Cache) GetOldest() (key, value interface{}, ok bool) {
|
||||||
c.lock.Lock()
|
c.lock.RLock()
|
||||||
key, value, ok = c.lru.GetOldest()
|
key, value, ok = c.lru.GetOldest()
|
||||||
c.lock.Unlock()
|
c.lock.RUnlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ type entry struct {
|
||||||
// NewLRU constructs an LRU of the given size
|
// NewLRU constructs an LRU of the given size
|
||||||
func NewLRU(size int, onEvict EvictCallback) (*LRU, error) {
|
func NewLRU(size int, onEvict EvictCallback) (*LRU, error) {
|
||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
return nil, errors.New("Must provide a positive size")
|
return nil, errors.New("must provide a positive size")
|
||||||
}
|
}
|
||||||
c := &LRU{
|
c := &LRU{
|
||||||
size: size,
|
size: size,
|
||||||
|
|
@ -109,7 +109,7 @@ func (c *LRU) Remove(key interface{}) (present bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveOldest removes the oldest item from the cache.
|
// RemoveOldest removes the oldest item from the cache.
|
||||||
func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *LRU) RemoveOldest() (key, value interface{}, ok bool) {
|
||||||
ent := c.evictList.Back()
|
ent := c.evictList.Back()
|
||||||
if ent != nil {
|
if ent != nil {
|
||||||
c.removeElement(ent)
|
c.removeElement(ent)
|
||||||
|
|
@ -120,7 +120,7 @@ func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOldest returns the oldest entry
|
// GetOldest returns the oldest entry
|
||||||
func (c *LRU) GetOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *LRU) GetOldest() (key, value interface{}, ok bool) {
|
||||||
ent := c.evictList.Back()
|
ent := c.evictList.Back()
|
||||||
if ent != nil {
|
if ent != nil {
|
||||||
kv := ent.Value.(*entry)
|
kv := ent.Value.(*entry)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
// Package simplelru provides simple LRU implementation based on build-in container/list.
|
||||||
package simplelru
|
package simplelru
|
||||||
|
|
||||||
// LRUCache is the interface for simple LRU cache.
|
// LRUCache is the interface for simple LRU cache.
|
||||||
|
|
@ -34,6 +35,6 @@ type LRUCache interface {
|
||||||
// Clears all cache entries.
|
// Clears all cache entries.
|
||||||
Purge()
|
Purge()
|
||||||
|
|
||||||
// Resizes cache, returning number evicted
|
// Resizes cache, returning number evicted
|
||||||
Resize(int) int
|
Resize(int) int
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package lru
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getRand(tb testing.TB) int64 {
|
||||||
|
out, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
|
||||||
|
if err != nil {
|
||||||
|
tb.Fatal(err)
|
||||||
|
}
|
||||||
|
return out.Int64()
|
||||||
|
}
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
Copyright (c) 2016 Uber Technologies, Inc.
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- megacheck
|
||||||
|
- revive
|
||||||
|
- govet
|
||||||
|
- unconvert
|
||||||
|
- megacheck
|
||||||
|
- gas
|
||||||
|
- gocyclo
|
||||||
|
- dupl
|
||||||
|
- misspell
|
||||||
|
- unparam
|
||||||
|
- unused
|
||||||
|
- typecheck
|
||||||
|
- ineffassign
|
||||||
|
- stylecheck
|
||||||
|
- exportloopref
|
||||||
|
- gocritic
|
||||||
|
- nakedret
|
||||||
|
- gosimple
|
||||||
|
- prealloc
|
||||||
|
fast: false
|
||||||
|
disable-all: true
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-rules:
|
||||||
|
- path: _test\.go
|
||||||
|
linters:
|
||||||
|
- dupl
|
||||||
|
exclude-use-default: false
|
||||||
|
|
@ -44,7 +44,7 @@ func New2Q(size int) (*TwoQueueCache, error) {
|
||||||
|
|
||||||
// New2QParams creates a new TwoQueueCache using the provided
|
// New2QParams creates a new TwoQueueCache using the provided
|
||||||
// parameter values.
|
// parameter values.
|
||||||
func New2QParams(size int, recentRatio float64, ghostRatio float64) (*TwoQueueCache, error) {
|
func New2QParams(size int, recentRatio, ghostRatio float64) (*TwoQueueCache, error) {
|
||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
return nil, fmt.Errorf("invalid size")
|
return nil, fmt.Errorf("invalid size")
|
||||||
}
|
}
|
||||||
|
|
@ -138,7 +138,6 @@ func (c *TwoQueueCache) Add(key, value interface{}) {
|
||||||
// Add to the recently seen list
|
// Add to the recently seen list
|
||||||
c.ensureSpace(false)
|
c.ensureSpace(false)
|
||||||
c.recent.Add(key, value)
|
c.recent.Add(key, value)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensureSpace is used to ensure we have space in the cache
|
// ensureSpace is used to ensure we have space in the cache
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
Copyright (c) 2014 HashiCorp, Inc.
|
||||||
|
|
||||||
Mozilla Public License, version 2.0
|
Mozilla Public License, version 2.0
|
||||||
|
|
||||||
1. Definitions
|
1. Definitions
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,7 @@
|
||||||
golang-lru
|
golang-lru
|
||||||
==========
|
==========
|
||||||
|
|
||||||
This provides the `lru` package which implements a fixed-size
|
Please upgrade to github.com/hashicorp/golang-lru/v2 for all new code as v1 will
|
||||||
thread safe LRU cache. It is based on the cache in Groupcache.
|
not be updated anymore. The v2 version supports generics and is faster; old code
|
||||||
|
can specify a specific tag, e.g. github.com/hashicorp/golang-lru/v1.0.2 for
|
||||||
Documentation
|
backwards compatibility.
|
||||||
=============
|
|
||||||
|
|
||||||
Full docs are available on [Godoc](http://godoc.org/github.com/hashicorp/golang-lru)
|
|
||||||
|
|
||||||
Example
|
|
||||||
=======
|
|
||||||
|
|
||||||
Using the LRU is very simple:
|
|
||||||
|
|
||||||
```go
|
|
||||||
l, _ := New(128)
|
|
||||||
for i := 0; i < 256; i++ {
|
|
||||||
l.Add(i, nil)
|
|
||||||
}
|
|
||||||
if l.Len() != 128 {
|
|
||||||
panic(fmt.Sprintf("bad len: %v", l.Len()))
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,6 @@ func (c *ARCCache) Add(key, value interface{}) {
|
||||||
|
|
||||||
// Add to the recently seen list
|
// Add to the recently seen list
|
||||||
c.t1.Add(key, value)
|
c.t1.Add(key, value)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace is used to adaptively evict from either T1 or T2
|
// replace is used to adaptively evict from either T1 or T2
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,17 @@ import (
|
||||||
"github.com/hashicorp/golang-lru/simplelru"
|
"github.com/hashicorp/golang-lru/simplelru"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultEvictedBufferSize defines the default buffer size to store evicted key/val
|
||||||
|
DefaultEvictedBufferSize = 16
|
||||||
|
)
|
||||||
|
|
||||||
// Cache is a thread-safe fixed size LRU cache.
|
// Cache is a thread-safe fixed size LRU cache.
|
||||||
type Cache struct {
|
type Cache struct {
|
||||||
lru simplelru.LRUCache
|
lru *simplelru.LRU
|
||||||
lock sync.RWMutex
|
evictedKeys, evictedVals []interface{}
|
||||||
|
onEvictedCB func(k, v interface{})
|
||||||
|
lock sync.RWMutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates an LRU of the given size.
|
// New creates an LRU of the given size.
|
||||||
|
|
@ -19,30 +26,63 @@ func New(size int) (*Cache, error) {
|
||||||
|
|
||||||
// NewWithEvict constructs a fixed size cache with the given eviction
|
// NewWithEvict constructs a fixed size cache with the given eviction
|
||||||
// callback.
|
// callback.
|
||||||
func NewWithEvict(size int, onEvicted func(key interface{}, value interface{})) (*Cache, error) {
|
func NewWithEvict(size int, onEvicted func(key, value interface{})) (c *Cache, err error) {
|
||||||
lru, err := simplelru.NewLRU(size, simplelru.EvictCallback(onEvicted))
|
// create a cache with default settings
|
||||||
if err != nil {
|
c = &Cache{
|
||||||
return nil, err
|
onEvictedCB: onEvicted,
|
||||||
}
|
}
|
||||||
c := &Cache{
|
if onEvicted != nil {
|
||||||
lru: lru,
|
c.initEvictBuffers()
|
||||||
|
onEvicted = c.onEvicted
|
||||||
}
|
}
|
||||||
return c, nil
|
c.lru, err = simplelru.NewLRU(size, onEvicted)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cache) initEvictBuffers() {
|
||||||
|
c.evictedKeys = make([]interface{}, 0, DefaultEvictedBufferSize)
|
||||||
|
c.evictedVals = make([]interface{}, 0, DefaultEvictedBufferSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// onEvicted save evicted key/val and sent in externally registered callback
|
||||||
|
// outside of critical section
|
||||||
|
func (c *Cache) onEvicted(k, v interface{}) {
|
||||||
|
c.evictedKeys = append(c.evictedKeys, k)
|
||||||
|
c.evictedVals = append(c.evictedVals, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Purge is used to completely clear the cache.
|
// Purge is used to completely clear the cache.
|
||||||
func (c *Cache) Purge() {
|
func (c *Cache) Purge() {
|
||||||
|
var ks, vs []interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
c.lru.Purge()
|
c.lru.Purge()
|
||||||
|
if c.onEvictedCB != nil && len(c.evictedKeys) > 0 {
|
||||||
|
ks, vs = c.evictedKeys, c.evictedVals
|
||||||
|
c.initEvictBuffers()
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
// invoke callback outside of critical section
|
||||||
|
if c.onEvictedCB != nil {
|
||||||
|
for i := 0; i < len(ks); i++ {
|
||||||
|
c.onEvictedCB(ks[i], vs[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add adds a value to the cache. Returns true if an eviction occurred.
|
// Add adds a value to the cache. Returns true if an eviction occurred.
|
||||||
func (c *Cache) Add(key, value interface{}) (evicted bool) {
|
func (c *Cache) Add(key, value interface{}) (evicted bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
evicted = c.lru.Add(key, value)
|
evicted = c.lru.Add(key, value)
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
return evicted
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get looks up a key's value from the cache.
|
// Get looks up a key's value from the cache.
|
||||||
|
|
@ -75,13 +115,21 @@ func (c *Cache) Peek(key interface{}) (value interface{}, ok bool) {
|
||||||
// recent-ness or deleting it for being stale, and if not, adds the value.
|
// recent-ness or deleting it for being stale, and if not, adds the value.
|
||||||
// Returns whether found and whether an eviction occurred.
|
// Returns whether found and whether an eviction occurred.
|
||||||
func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
|
func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
if c.lru.Contains(key) {
|
if c.lru.Contains(key) {
|
||||||
|
c.lock.Unlock()
|
||||||
return true, false
|
return true, false
|
||||||
}
|
}
|
||||||
evicted = c.lru.Add(key, value)
|
evicted = c.lru.Add(key, value)
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return false, evicted
|
return false, evicted
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,47 +137,80 @@ func (c *Cache) ContainsOrAdd(key, value interface{}) (ok, evicted bool) {
|
||||||
// recent-ness or deleting it for being stale, and if not, adds the value.
|
// recent-ness or deleting it for being stale, and if not, adds the value.
|
||||||
// Returns whether found and whether an eviction occurred.
|
// Returns whether found and whether an eviction occurred.
|
||||||
func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evicted bool) {
|
func (c *Cache) PeekOrAdd(key, value interface{}) (previous interface{}, ok, evicted bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
|
||||||
|
|
||||||
previous, ok = c.lru.Peek(key)
|
previous, ok = c.lru.Peek(key)
|
||||||
if ok {
|
if ok {
|
||||||
|
c.lock.Unlock()
|
||||||
return previous, true, false
|
return previous, true, false
|
||||||
}
|
}
|
||||||
|
|
||||||
evicted = c.lru.Add(key, value)
|
evicted = c.lru.Add(key, value)
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && evicted {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return nil, false, evicted
|
return nil, false, evicted
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove removes the provided key from the cache.
|
// Remove removes the provided key from the cache.
|
||||||
func (c *Cache) Remove(key interface{}) (present bool) {
|
func (c *Cache) Remove(key interface{}) (present bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
present = c.lru.Remove(key)
|
present = c.lru.Remove(key)
|
||||||
|
if c.onEvictedCB != nil && present {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && present {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize changes the cache size.
|
// Resize changes the cache size.
|
||||||
func (c *Cache) Resize(size int) (evicted int) {
|
func (c *Cache) Resize(size int) (evicted int) {
|
||||||
|
var ks, vs []interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
evicted = c.lru.Resize(size)
|
evicted = c.lru.Resize(size)
|
||||||
|
if c.onEvictedCB != nil && evicted > 0 {
|
||||||
|
ks, vs = c.evictedKeys, c.evictedVals
|
||||||
|
c.initEvictBuffers()
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && evicted > 0 {
|
||||||
|
for i := 0; i < len(ks); i++ {
|
||||||
|
c.onEvictedCB(ks[i], vs[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
return evicted
|
return evicted
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveOldest removes the oldest item from the cache.
|
// RemoveOldest removes the oldest item from the cache.
|
||||||
func (c *Cache) RemoveOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *Cache) RemoveOldest() (key, value interface{}, ok bool) {
|
||||||
|
var k, v interface{}
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
key, value, ok = c.lru.RemoveOldest()
|
key, value, ok = c.lru.RemoveOldest()
|
||||||
|
if c.onEvictedCB != nil && ok {
|
||||||
|
k, v = c.evictedKeys[0], c.evictedVals[0]
|
||||||
|
c.evictedKeys, c.evictedVals = c.evictedKeys[:0], c.evictedVals[:0]
|
||||||
|
}
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
if c.onEvictedCB != nil && ok {
|
||||||
|
c.onEvictedCB(k, v)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOldest returns the oldest entry
|
// GetOldest returns the oldest entry
|
||||||
func (c *Cache) GetOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *Cache) GetOldest() (key, value interface{}, ok bool) {
|
||||||
c.lock.Lock()
|
c.lock.RLock()
|
||||||
key, value, ok = c.lru.GetOldest()
|
key, value, ok = c.lru.GetOldest()
|
||||||
c.lock.Unlock()
|
c.lock.RUnlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ type entry struct {
|
||||||
// NewLRU constructs an LRU of the given size
|
// NewLRU constructs an LRU of the given size
|
||||||
func NewLRU(size int, onEvict EvictCallback) (*LRU, error) {
|
func NewLRU(size int, onEvict EvictCallback) (*LRU, error) {
|
||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
return nil, errors.New("Must provide a positive size")
|
return nil, errors.New("must provide a positive size")
|
||||||
}
|
}
|
||||||
c := &LRU{
|
c := &LRU{
|
||||||
size: size,
|
size: size,
|
||||||
|
|
@ -109,7 +109,7 @@ func (c *LRU) Remove(key interface{}) (present bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveOldest removes the oldest item from the cache.
|
// RemoveOldest removes the oldest item from the cache.
|
||||||
func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *LRU) RemoveOldest() (key, value interface{}, ok bool) {
|
||||||
ent := c.evictList.Back()
|
ent := c.evictList.Back()
|
||||||
if ent != nil {
|
if ent != nil {
|
||||||
c.removeElement(ent)
|
c.removeElement(ent)
|
||||||
|
|
@ -120,7 +120,7 @@ func (c *LRU) RemoveOldest() (key interface{}, value interface{}, ok bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOldest returns the oldest entry
|
// GetOldest returns the oldest entry
|
||||||
func (c *LRU) GetOldest() (key interface{}, value interface{}, ok bool) {
|
func (c *LRU) GetOldest() (key, value interface{}, ok bool) {
|
||||||
ent := c.evictList.Back()
|
ent := c.evictList.Back()
|
||||||
if ent != nil {
|
if ent != nil {
|
||||||
kv := ent.Value.(*entry)
|
kv := ent.Value.(*entry)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
// Package simplelru provides simple LRU implementation based on build-in container/list.
|
||||||
package simplelru
|
package simplelru
|
||||||
|
|
||||||
// LRUCache is the interface for simple LRU cache.
|
// LRUCache is the interface for simple LRU cache.
|
||||||
|
|
@ -34,6 +35,6 @@ type LRUCache interface {
|
||||||
// Clears all cache entries.
|
// Clears all cache entries.
|
||||||
Purge()
|
Purge()
|
||||||
|
|
||||||
// Resizes cache, returning number evicted
|
// Resizes cache, returning number evicted
|
||||||
Resize(int) int
|
Resize(int) int
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package lru
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getRand(tb testing.TB) int64 {
|
||||||
|
out, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt64))
|
||||||
|
if err != nil {
|
||||||
|
tb.Fatal(err)
|
||||||
|
}
|
||||||
|
return out.Int64()
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,22 @@
|
||||||
Releases
|
Releases
|
||||||
========
|
========
|
||||||
|
|
||||||
|
v1.10.0 (2023-03-08)
|
||||||
|
====================
|
||||||
|
|
||||||
|
- Comply with Go 1.20's multiple-error interface.
|
||||||
|
- Drop Go 1.18 support.
|
||||||
|
Per the support policy, only Go 1.19 and 1.20 are supported now.
|
||||||
|
- Drop all non-test external dependencies.
|
||||||
|
|
||||||
|
v1.9.0 (2022-12-12)
|
||||||
|
===================
|
||||||
|
|
||||||
|
- Add `AppendFunc` that allow passsing functions to similar to
|
||||||
|
`AppendInvoke`.
|
||||||
|
|
||||||
|
- Bump up yaml.v3 dependency to 3.0.1.
|
||||||
|
|
||||||
v1.8.0 (2022-02-28)
|
v1.8.0 (2022-02-28)
|
||||||
===================
|
===================
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,29 @@
|
||||||
|
|
||||||
`multierr` allows combining one or more Go `error`s together.
|
`multierr` allows combining one or more Go `error`s together.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Idiomatic**:
|
||||||
|
multierr follows best practices in Go, and keeps your code idiomatic.
|
||||||
|
- It keeps the underlying error type hidden,
|
||||||
|
allowing you to deal in `error` values exclusively.
|
||||||
|
- It provides APIs to safely append into an error from a `defer` statement.
|
||||||
|
- **Performant**:
|
||||||
|
multierr is optimized for performance:
|
||||||
|
- It avoids allocations where possible.
|
||||||
|
- It utilizes slice resizing semantics to optimize common cases
|
||||||
|
like appending into the same error object from a loop.
|
||||||
|
- **Interoperable**:
|
||||||
|
multierr interoperates with the Go standard library's error APIs seamlessly:
|
||||||
|
- The `errors.Is` and `errors.As` functions *just work*.
|
||||||
|
- **Lightweight**:
|
||||||
|
multierr comes with virtually no dependencies.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
go get -u go.uber.org/multierr
|
```bash
|
||||||
|
go get -u go.uber.org/multierr@latest
|
||||||
|
```
|
||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2017-2021 Uber Technologies, Inc.
|
// Copyright (c) 2017-2023 Uber Technologies, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
@ -20,106 +20,109 @@
|
||||||
|
|
||||||
// Package multierr allows combining one or more errors together.
|
// Package multierr allows combining one or more errors together.
|
||||||
//
|
//
|
||||||
// Overview
|
// # Overview
|
||||||
//
|
//
|
||||||
// Errors can be combined with the use of the Combine function.
|
// Errors can be combined with the use of the Combine function.
|
||||||
//
|
//
|
||||||
// multierr.Combine(
|
// multierr.Combine(
|
||||||
// reader.Close(),
|
// reader.Close(),
|
||||||
// writer.Close(),
|
// writer.Close(),
|
||||||
// conn.Close(),
|
// conn.Close(),
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// If only two errors are being combined, the Append function may be used
|
// If only two errors are being combined, the Append function may be used
|
||||||
// instead.
|
// instead.
|
||||||
//
|
//
|
||||||
// err = multierr.Append(reader.Close(), writer.Close())
|
// err = multierr.Append(reader.Close(), writer.Close())
|
||||||
//
|
//
|
||||||
// The underlying list of errors for a returned error object may be retrieved
|
// The underlying list of errors for a returned error object may be retrieved
|
||||||
// with the Errors function.
|
// with the Errors function.
|
||||||
//
|
//
|
||||||
// errors := multierr.Errors(err)
|
// errors := multierr.Errors(err)
|
||||||
// if len(errors) > 0 {
|
// if len(errors) > 0 {
|
||||||
// fmt.Println("The following errors occurred:", errors)
|
// fmt.Println("The following errors occurred:", errors)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Appending from a loop
|
// # Appending from a loop
|
||||||
//
|
//
|
||||||
// You sometimes need to append into an error from a loop.
|
// You sometimes need to append into an error from a loop.
|
||||||
//
|
//
|
||||||
// var err error
|
// var err error
|
||||||
// for _, item := range items {
|
// for _, item := range items {
|
||||||
// err = multierr.Append(err, process(item))
|
// err = multierr.Append(err, process(item))
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Cases like this may require knowledge of whether an individual instance
|
// Cases like this may require knowledge of whether an individual instance
|
||||||
// failed. This usually requires introduction of a new variable.
|
// failed. This usually requires introduction of a new variable.
|
||||||
//
|
//
|
||||||
// var err error
|
// var err error
|
||||||
// for _, item := range items {
|
// for _, item := range items {
|
||||||
// if perr := process(item); perr != nil {
|
// if perr := process(item); perr != nil {
|
||||||
// log.Warn("skipping item", item)
|
// log.Warn("skipping item", item)
|
||||||
// err = multierr.Append(err, perr)
|
// err = multierr.Append(err, perr)
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// multierr includes AppendInto to simplify cases like this.
|
// multierr includes AppendInto to simplify cases like this.
|
||||||
//
|
//
|
||||||
// var err error
|
// var err error
|
||||||
// for _, item := range items {
|
// for _, item := range items {
|
||||||
// if multierr.AppendInto(&err, process(item)) {
|
// if multierr.AppendInto(&err, process(item)) {
|
||||||
// log.Warn("skipping item", item)
|
// log.Warn("skipping item", item)
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// This will append the error into the err variable, and return true if that
|
// This will append the error into the err variable, and return true if that
|
||||||
// individual error was non-nil.
|
// individual error was non-nil.
|
||||||
//
|
//
|
||||||
// See AppendInto for more information.
|
// See [AppendInto] for more information.
|
||||||
//
|
//
|
||||||
// Deferred Functions
|
// # Deferred Functions
|
||||||
//
|
//
|
||||||
// Go makes it possible to modify the return value of a function in a defer
|
// Go makes it possible to modify the return value of a function in a defer
|
||||||
// block if the function was using named returns. This makes it possible to
|
// block if the function was using named returns. This makes it possible to
|
||||||
// record resource cleanup failures from deferred blocks.
|
// record resource cleanup failures from deferred blocks.
|
||||||
//
|
//
|
||||||
// func sendRequest(req Request) (err error) {
|
// func sendRequest(req Request) (err error) {
|
||||||
// conn, err := openConnection()
|
// conn, err := openConnection()
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return err
|
// return err
|
||||||
// }
|
// }
|
||||||
// defer func() {
|
// defer func() {
|
||||||
// err = multierr.Append(err, conn.Close())
|
// err = multierr.Append(err, conn.Close())
|
||||||
// }()
|
// }()
|
||||||
// // ...
|
// // ...
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// multierr provides the Invoker type and AppendInvoke function to make cases
|
// multierr provides the Invoker type and AppendInvoke function to make cases
|
||||||
// like the above simpler and obviate the need for a closure. The following is
|
// like the above simpler and obviate the need for a closure. The following is
|
||||||
// roughly equivalent to the example above.
|
// roughly equivalent to the example above.
|
||||||
//
|
//
|
||||||
// func sendRequest(req Request) (err error) {
|
// func sendRequest(req Request) (err error) {
|
||||||
// conn, err := openConnection()
|
// conn, err := openConnection()
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return err
|
// return err
|
||||||
// }
|
// }
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Close(conn))
|
// defer multierr.AppendInvoke(&err, multierr.Close(conn))
|
||||||
// // ...
|
// // ...
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// See AppendInvoke and Invoker for more information.
|
// See [AppendInvoke] and [Invoker] for more information.
|
||||||
//
|
//
|
||||||
// Advanced Usage
|
// NOTE: If you're modifying an error from inside a defer, you MUST use a named
|
||||||
|
// return value for that function.
|
||||||
|
//
|
||||||
|
// # Advanced Usage
|
||||||
//
|
//
|
||||||
// Errors returned by Combine and Append MAY implement the following
|
// Errors returned by Combine and Append MAY implement the following
|
||||||
// interface.
|
// interface.
|
||||||
//
|
//
|
||||||
// type errorGroup interface {
|
// type errorGroup interface {
|
||||||
// // Returns a slice containing the underlying list of errors.
|
// // Returns a slice containing the underlying list of errors.
|
||||||
// //
|
// //
|
||||||
// // This slice MUST NOT be modified by the caller.
|
// // This slice MUST NOT be modified by the caller.
|
||||||
// Errors() []error
|
// Errors() []error
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Note that if you need access to list of errors behind a multierr error, you
|
// Note that if you need access to list of errors behind a multierr error, you
|
||||||
// should prefer using the Errors function. That said, if you need cheap
|
// should prefer using the Errors function. That said, if you need cheap
|
||||||
|
|
@ -128,24 +131,22 @@
|
||||||
// because errors returned by Combine and Append are not guaranteed to
|
// because errors returned by Combine and Append are not guaranteed to
|
||||||
// implement this interface.
|
// implement this interface.
|
||||||
//
|
//
|
||||||
// var errors []error
|
// var errors []error
|
||||||
// group, ok := err.(errorGroup)
|
// group, ok := err.(errorGroup)
|
||||||
// if ok {
|
// if ok {
|
||||||
// errors = group.Errors()
|
// errors = group.Errors()
|
||||||
// } else {
|
// } else {
|
||||||
// errors = []error{err}
|
// errors = []error{err}
|
||||||
// }
|
// }
|
||||||
package multierr // import "go.uber.org/multierr"
|
package multierr // import "go.uber.org/multierr"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"go.uber.org/atomic"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -185,8 +186,8 @@ type errorGroup interface {
|
||||||
// Errors returns a slice containing zero or more errors that the supplied
|
// Errors returns a slice containing zero or more errors that the supplied
|
||||||
// error is composed of. If the error is nil, a nil slice is returned.
|
// error is composed of. If the error is nil, a nil slice is returned.
|
||||||
//
|
//
|
||||||
// err := multierr.Append(r.Close(), w.Close())
|
// err := multierr.Append(r.Close(), w.Close())
|
||||||
// errors := multierr.Errors(err)
|
// errors := multierr.Errors(err)
|
||||||
//
|
//
|
||||||
// If the error is not composed of other errors, the returned slice contains
|
// If the error is not composed of other errors, the returned slice contains
|
||||||
// just the error that was passed in.
|
// just the error that was passed in.
|
||||||
|
|
@ -209,10 +210,7 @@ func Errors(err error) []error {
|
||||||
return []error{err}
|
return []error{err}
|
||||||
}
|
}
|
||||||
|
|
||||||
errors := eg.Errors()
|
return append(([]error)(nil), eg.Errors()...)
|
||||||
result := make([]error, len(errors))
|
|
||||||
copy(result, errors)
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiError is an error that holds one or more errors.
|
// multiError is an error that holds one or more errors.
|
||||||
|
|
@ -239,33 +237,6 @@ func (merr *multiError) Errors() []error {
|
||||||
return merr.errors
|
return merr.errors
|
||||||
}
|
}
|
||||||
|
|
||||||
// As attempts to find the first error in the error list that matches the type
|
|
||||||
// of the value that target points to.
|
|
||||||
//
|
|
||||||
// This function allows errors.As to traverse the values stored on the
|
|
||||||
// multierr error.
|
|
||||||
func (merr *multiError) As(target interface{}) bool {
|
|
||||||
for _, err := range merr.Errors() {
|
|
||||||
if errors.As(err, target) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is attempts to match the provided error against errors in the error list.
|
|
||||||
//
|
|
||||||
// This function allows errors.Is to traverse the values stored on the
|
|
||||||
// multierr error.
|
|
||||||
func (merr *multiError) Is(target error) bool {
|
|
||||||
for _, err := range merr.Errors() {
|
|
||||||
if errors.Is(err, target) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (merr *multiError) Error() string {
|
func (merr *multiError) Error() string {
|
||||||
if merr == nil {
|
if merr == nil {
|
||||||
return ""
|
return ""
|
||||||
|
|
@ -393,8 +364,7 @@ func fromSlice(errors []error) error {
|
||||||
// Otherwise "errors" escapes to the heap
|
// Otherwise "errors" escapes to the heap
|
||||||
// unconditionally for all other cases.
|
// unconditionally for all other cases.
|
||||||
// This lets us optimize for the "no errors" case.
|
// This lets us optimize for the "no errors" case.
|
||||||
out := make([]error, len(errors))
|
out := append(([]error)(nil), errors...)
|
||||||
copy(out, errors)
|
|
||||||
return &multiError{errors: out}
|
return &multiError{errors: out}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -420,32 +390,32 @@ func fromSlice(errors []error) error {
|
||||||
// If zero arguments were passed or if all items are nil, a nil error is
|
// If zero arguments were passed or if all items are nil, a nil error is
|
||||||
// returned.
|
// returned.
|
||||||
//
|
//
|
||||||
// Combine(nil, nil) // == nil
|
// Combine(nil, nil) // == nil
|
||||||
//
|
//
|
||||||
// If only a single error was passed, it is returned as-is.
|
// If only a single error was passed, it is returned as-is.
|
||||||
//
|
//
|
||||||
// Combine(err) // == err
|
// Combine(err) // == err
|
||||||
//
|
//
|
||||||
// Combine skips over nil arguments so this function may be used to combine
|
// Combine skips over nil arguments so this function may be used to combine
|
||||||
// together errors from operations that fail independently of each other.
|
// together errors from operations that fail independently of each other.
|
||||||
//
|
//
|
||||||
// multierr.Combine(
|
// multierr.Combine(
|
||||||
// reader.Close(),
|
// reader.Close(),
|
||||||
// writer.Close(),
|
// writer.Close(),
|
||||||
// pipe.Close(),
|
// pipe.Close(),
|
||||||
// )
|
// )
|
||||||
//
|
//
|
||||||
// If any of the passed errors is a multierr error, it will be flattened along
|
// If any of the passed errors is a multierr error, it will be flattened along
|
||||||
// with the other errors.
|
// with the other errors.
|
||||||
//
|
//
|
||||||
// multierr.Combine(multierr.Combine(err1, err2), err3)
|
// multierr.Combine(multierr.Combine(err1, err2), err3)
|
||||||
// // is the same as
|
// // is the same as
|
||||||
// multierr.Combine(err1, err2, err3)
|
// multierr.Combine(err1, err2, err3)
|
||||||
//
|
//
|
||||||
// The returned error formats into a readable multi-line error message if
|
// The returned error formats into a readable multi-line error message if
|
||||||
// formatted with %+v.
|
// formatted with %+v.
|
||||||
//
|
//
|
||||||
// fmt.Sprintf("%+v", multierr.Combine(err1, err2))
|
// fmt.Sprintf("%+v", multierr.Combine(err1, err2))
|
||||||
func Combine(errors ...error) error {
|
func Combine(errors ...error) error {
|
||||||
return fromSlice(errors)
|
return fromSlice(errors)
|
||||||
}
|
}
|
||||||
|
|
@ -455,16 +425,19 @@ func Combine(errors ...error) error {
|
||||||
// This function is a specialization of Combine for the common case where
|
// This function is a specialization of Combine for the common case where
|
||||||
// there are only two errors.
|
// there are only two errors.
|
||||||
//
|
//
|
||||||
// err = multierr.Append(reader.Close(), writer.Close())
|
// err = multierr.Append(reader.Close(), writer.Close())
|
||||||
//
|
//
|
||||||
// The following pattern may also be used to record failure of deferred
|
// The following pattern may also be used to record failure of deferred
|
||||||
// operations without losing information about the original error.
|
// operations without losing information about the original error.
|
||||||
//
|
//
|
||||||
// func doSomething(..) (err error) {
|
// func doSomething(..) (err error) {
|
||||||
// f := acquireResource()
|
// f := acquireResource()
|
||||||
// defer func() {
|
// defer func() {
|
||||||
// err = multierr.Append(err, f.Close())
|
// err = multierr.Append(err, f.Close())
|
||||||
// }()
|
// }()
|
||||||
|
//
|
||||||
|
// Note that the variable MUST be a named return to append an error to it from
|
||||||
|
// the defer statement. See also [AppendInvoke].
|
||||||
func Append(left error, right error) error {
|
func Append(left error, right error) error {
|
||||||
switch {
|
switch {
|
||||||
case left == nil:
|
case left == nil:
|
||||||
|
|
@ -494,37 +467,37 @@ func Append(left error, right error) error {
|
||||||
// AppendInto appends an error into the destination of an error pointer and
|
// AppendInto appends an error into the destination of an error pointer and
|
||||||
// returns whether the error being appended was non-nil.
|
// returns whether the error being appended was non-nil.
|
||||||
//
|
//
|
||||||
// var err error
|
// var err error
|
||||||
// multierr.AppendInto(&err, r.Close())
|
// multierr.AppendInto(&err, r.Close())
|
||||||
// multierr.AppendInto(&err, w.Close())
|
// multierr.AppendInto(&err, w.Close())
|
||||||
//
|
//
|
||||||
// The above is equivalent to,
|
// The above is equivalent to,
|
||||||
//
|
//
|
||||||
// err := multierr.Append(r.Close(), w.Close())
|
// err := multierr.Append(r.Close(), w.Close())
|
||||||
//
|
//
|
||||||
// As AppendInto reports whether the provided error was non-nil, it may be
|
// As AppendInto reports whether the provided error was non-nil, it may be
|
||||||
// used to build a multierr error in a loop more ergonomically. For example:
|
// used to build a multierr error in a loop more ergonomically. For example:
|
||||||
//
|
//
|
||||||
// var err error
|
// var err error
|
||||||
// for line := range lines {
|
// for line := range lines {
|
||||||
// var item Item
|
// var item Item
|
||||||
// if multierr.AppendInto(&err, parse(line, &item)) {
|
// if multierr.AppendInto(&err, parse(line, &item)) {
|
||||||
// continue
|
// continue
|
||||||
// }
|
// }
|
||||||
// items = append(items, item)
|
// items = append(items, item)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// Compare this with a version that relies solely on Append:
|
// Compare this with a version that relies solely on Append:
|
||||||
//
|
//
|
||||||
// var err error
|
// var err error
|
||||||
// for line := range lines {
|
// for line := range lines {
|
||||||
// var item Item
|
// var item Item
|
||||||
// if parseErr := parse(line, &item); parseErr != nil {
|
// if parseErr := parse(line, &item); parseErr != nil {
|
||||||
// err = multierr.Append(err, parseErr)
|
// err = multierr.Append(err, parseErr)
|
||||||
// continue
|
// continue
|
||||||
// }
|
// }
|
||||||
// items = append(items, item)
|
// items = append(items, item)
|
||||||
// }
|
// }
|
||||||
func AppendInto(into *error, err error) (errored bool) {
|
func AppendInto(into *error, err error) (errored bool) {
|
||||||
if into == nil {
|
if into == nil {
|
||||||
// We panic if 'into' is nil. This is not documented above
|
// We panic if 'into' is nil. This is not documented above
|
||||||
|
|
@ -545,7 +518,7 @@ func AppendInto(into *error, err error) (errored bool) {
|
||||||
// AppendInvoke to append the result of calling the function into an error.
|
// AppendInvoke to append the result of calling the function into an error.
|
||||||
// This allows you to conveniently defer capture of failing operations.
|
// This allows you to conveniently defer capture of failing operations.
|
||||||
//
|
//
|
||||||
// See also, Close and Invoke.
|
// See also, [Close] and [Invoke].
|
||||||
type Invoker interface {
|
type Invoker interface {
|
||||||
Invoke() error
|
Invoke() error
|
||||||
}
|
}
|
||||||
|
|
@ -556,19 +529,22 @@ type Invoker interface {
|
||||||
//
|
//
|
||||||
// For example,
|
// For example,
|
||||||
//
|
//
|
||||||
// func processReader(r io.Reader) (err error) {
|
// func processReader(r io.Reader) (err error) {
|
||||||
// scanner := bufio.NewScanner(r)
|
// scanner := bufio.NewScanner(r)
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
|
// defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
|
||||||
// for scanner.Scan() {
|
// for scanner.Scan() {
|
||||||
// // ...
|
// // ...
|
||||||
// }
|
// }
|
||||||
// // ...
|
// // ...
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// In this example, the following line will construct the Invoker right away,
|
// In this example, the following line will construct the Invoker right away,
|
||||||
// but defer the invocation of scanner.Err() until the function returns.
|
// but defer the invocation of scanner.Err() until the function returns.
|
||||||
//
|
//
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
|
// defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
|
||||||
|
//
|
||||||
|
// Note that the error you're appending to from the defer statement MUST be a
|
||||||
|
// named return.
|
||||||
type Invoke func() error
|
type Invoke func() error
|
||||||
|
|
||||||
// Invoke calls the supplied function and returns its result.
|
// Invoke calls the supplied function and returns its result.
|
||||||
|
|
@ -579,19 +555,22 @@ func (i Invoke) Invoke() error { return i() }
|
||||||
//
|
//
|
||||||
// For example,
|
// For example,
|
||||||
//
|
//
|
||||||
// func processFile(path string) (err error) {
|
// func processFile(path string) (err error) {
|
||||||
// f, err := os.Open(path)
|
// f, err := os.Open(path)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return err
|
// return err
|
||||||
// }
|
// }
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Close(f))
|
// defer multierr.AppendInvoke(&err, multierr.Close(f))
|
||||||
// return processReader(f)
|
// return processReader(f)
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// In this example, multierr.Close will construct the Invoker right away, but
|
// In this example, multierr.Close will construct the Invoker right away, but
|
||||||
// defer the invocation of f.Close until the function returns.
|
// defer the invocation of f.Close until the function returns.
|
||||||
//
|
//
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Close(f))
|
// defer multierr.AppendInvoke(&err, multierr.Close(f))
|
||||||
|
//
|
||||||
|
// Note that the error you're appending to from the defer statement MUST be a
|
||||||
|
// named return.
|
||||||
func Close(closer io.Closer) Invoker {
|
func Close(closer io.Closer) Invoker {
|
||||||
return Invoke(closer.Close)
|
return Invoke(closer.Close)
|
||||||
}
|
}
|
||||||
|
|
@ -601,52 +580,73 @@ func Close(closer io.Closer) Invoker {
|
||||||
// invocation of fallible operations until a function returns, and capture the
|
// invocation of fallible operations until a function returns, and capture the
|
||||||
// resulting errors.
|
// resulting errors.
|
||||||
//
|
//
|
||||||
// func doSomething(...) (err error) {
|
// func doSomething(...) (err error) {
|
||||||
// // ...
|
// // ...
|
||||||
// f, err := openFile(..)
|
// f, err := openFile(..)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return err
|
// return err
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// // multierr will call f.Close() when this function returns and
|
// // multierr will call f.Close() when this function returns and
|
||||||
// // if the operation fails, its append its error into the
|
// // if the operation fails, its append its error into the
|
||||||
// // returned error.
|
// // returned error.
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Close(f))
|
// defer multierr.AppendInvoke(&err, multierr.Close(f))
|
||||||
//
|
//
|
||||||
// scanner := bufio.NewScanner(f)
|
// scanner := bufio.NewScanner(f)
|
||||||
// // Similarly, this scheduled scanner.Err to be called and
|
// // Similarly, this scheduled scanner.Err to be called and
|
||||||
// // inspected when the function returns and append its error
|
// // inspected when the function returns and append its error
|
||||||
// // into the returned error.
|
// // into the returned error.
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
|
// defer multierr.AppendInvoke(&err, multierr.Invoke(scanner.Err))
|
||||||
//
|
//
|
||||||
// // ...
|
// // ...
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
|
// NOTE: If used with a defer, the error variable MUST be a named return.
|
||||||
//
|
//
|
||||||
// Without defer, AppendInvoke behaves exactly like AppendInto.
|
// Without defer, AppendInvoke behaves exactly like AppendInto.
|
||||||
//
|
//
|
||||||
// err := // ...
|
// err := // ...
|
||||||
// multierr.AppendInvoke(&err, mutltierr.Invoke(foo))
|
// multierr.AppendInvoke(&err, mutltierr.Invoke(foo))
|
||||||
//
|
//
|
||||||
// // ...is roughly equivalent to...
|
// // ...is roughly equivalent to...
|
||||||
//
|
//
|
||||||
// err := // ...
|
// err := // ...
|
||||||
// multierr.AppendInto(&err, foo())
|
// multierr.AppendInto(&err, foo())
|
||||||
//
|
//
|
||||||
// The advantage of the indirection introduced by Invoker is to make it easy
|
// The advantage of the indirection introduced by Invoker is to make it easy
|
||||||
// to defer the invocation of a function. Without this indirection, the
|
// to defer the invocation of a function. Without this indirection, the
|
||||||
// invoked function will be evaluated at the time of the defer block rather
|
// invoked function will be evaluated at the time of the defer block rather
|
||||||
// than when the function returns.
|
// than when the function returns.
|
||||||
//
|
//
|
||||||
// // BAD: This is likely not what the caller intended. This will evaluate
|
// // BAD: This is likely not what the caller intended. This will evaluate
|
||||||
// // foo() right away and append its result into the error when the
|
// // foo() right away and append its result into the error when the
|
||||||
// // function returns.
|
// // function returns.
|
||||||
// defer multierr.AppendInto(&err, foo())
|
// defer multierr.AppendInto(&err, foo())
|
||||||
//
|
//
|
||||||
// // GOOD: This will defer invocation of foo unutil the function returns.
|
// // GOOD: This will defer invocation of foo unutil the function returns.
|
||||||
// defer multierr.AppendInvoke(&err, multierr.Invoke(foo))
|
// defer multierr.AppendInvoke(&err, multierr.Invoke(foo))
|
||||||
//
|
//
|
||||||
// multierr provides a few Invoker implementations out of the box for
|
// multierr provides a few Invoker implementations out of the box for
|
||||||
// convenience. See Invoker for more information.
|
// convenience. See [Invoker] for more information.
|
||||||
func AppendInvoke(into *error, invoker Invoker) {
|
func AppendInvoke(into *error, invoker Invoker) {
|
||||||
AppendInto(into, invoker.Invoke())
|
AppendInto(into, invoker.Invoke())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppendFunc is a shorthand for [AppendInvoke].
|
||||||
|
// It allows using function or method value directly
|
||||||
|
// without having to wrap it into an [Invoker] interface.
|
||||||
|
//
|
||||||
|
// func doSomething(...) (err error) {
|
||||||
|
// w, err := startWorker(...)
|
||||||
|
// if err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // multierr will call w.Stop() when this function returns and
|
||||||
|
// // if the operation fails, it appends its error into the
|
||||||
|
// // returned error.
|
||||||
|
// defer multierr.AppendFunc(&err, w.Stop)
|
||||||
|
// }
|
||||||
|
func AppendFunc(into *error, fn func() error) {
|
||||||
|
AppendInvoke(into, Invoke(fn))
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
// Copyright (c) 2017-2023 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
//go:build go1.20
|
||||||
|
// +build go1.20
|
||||||
|
|
||||||
|
package multierr
|
||||||
|
|
||||||
|
// Unwrap returns a list of errors wrapped by this multierr.
|
||||||
|
func (merr *multiError) Unwrap() []error {
|
||||||
|
return merr.Errors()
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
// Copyright (c) 2017-2023 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
//go:build !go1.20
|
||||||
|
// +build !go1.20
|
||||||
|
|
||||||
|
package multierr
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
// Versions of Go before 1.20 did not support the Unwrap() []error method.
|
||||||
|
// This provides a similar behavior by implementing the Is(..) and As(..)
|
||||||
|
// methods.
|
||||||
|
// See the errors.Join proposal for details:
|
||||||
|
// https://github.com/golang/go/issues/53435
|
||||||
|
|
||||||
|
// As attempts to find the first error in the error list that matches the type
|
||||||
|
// of the value that target points to.
|
||||||
|
//
|
||||||
|
// This function allows errors.As to traverse the values stored on the
|
||||||
|
// multierr error.
|
||||||
|
func (merr *multiError) As(target interface{}) bool {
|
||||||
|
for _, err := range merr.Errors() {
|
||||||
|
if errors.As(err, target) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is attempts to match the provided error against errors in the error list.
|
||||||
|
//
|
||||||
|
// This function allows errors.Is to traverse the values stored on the
|
||||||
|
// multierr error.
|
||||||
|
func (merr *multiError) Is(target error) bool {
|
||||||
|
for _, err := range merr.Errors() {
|
||||||
|
if errors.Is(err, target) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
package: go.uber.org/multierr
|
|
||||||
import:
|
|
||||||
- package: go.uber.org/atomic
|
|
||||||
version: ^1
|
|
||||||
testImport:
|
|
||||||
- package: github.com/stretchr/testify
|
|
||||||
subpackages:
|
|
||||||
- assert
|
|
||||||
|
|
@ -3,6 +3,27 @@ All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## 1.25.0 (1 Aug 2023)
|
||||||
|
|
||||||
|
This release contains several improvements including performance, API additions,
|
||||||
|
and two new experimental packages whose APIs are unstable and may change in the
|
||||||
|
future.
|
||||||
|
|
||||||
|
Enhancements:
|
||||||
|
* [#1246][]: Add `zap/exp/zapslog` package for integration with slog.
|
||||||
|
* [#1273][]: Add `Name` to `Logger` which returns the Logger's name if one is set.
|
||||||
|
* [#1281][]: Add `zap/exp/expfield` package which contains helper methods
|
||||||
|
`Str` and `Strs` for constructing String-like zap.Fields.
|
||||||
|
* [#1310][]: Reduce stack size on `Any`.
|
||||||
|
|
||||||
|
Thanks to @knight42, @dzakaammar, @bcspragu, and @rexywork for their contributions
|
||||||
|
to this release.
|
||||||
|
|
||||||
|
[#1246]: https://github.com/uber-go/zap/pull/1246
|
||||||
|
[#1273]: https://github.com/uber-go/zap/pull/1273
|
||||||
|
[#1281]: https://github.com/uber-go/zap/pull/1281
|
||||||
|
[#1310]: https://github.com/uber-go/zap/pull/1310
|
||||||
|
|
||||||
## 1.24.0 (30 Nov 2022)
|
## 1.24.0 (30 Nov 2022)
|
||||||
|
|
||||||
Enhancements:
|
Enhancements:
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
export GOBIN ?= $(shell pwd)/bin
|
export GOBIN ?= $(shell pwd)/bin
|
||||||
|
|
||||||
GOLINT = $(GOBIN)/golint
|
REVIVE = $(GOBIN)/revive
|
||||||
STATICCHECK = $(GOBIN)/staticcheck
|
STATICCHECK = $(GOBIN)/staticcheck
|
||||||
|
GOVULNCHECK = $(GOBIN)/govulncheck
|
||||||
BENCH_FLAGS ?= -cpuprofile=cpu.pprof -memprofile=mem.pprof -benchmem
|
BENCH_FLAGS ?= -cpuprofile=cpu.pprof -memprofile=mem.pprof -benchmem
|
||||||
|
|
||||||
# Directories containing independent Go modules.
|
# Directories containing independent Go modules.
|
||||||
#
|
#
|
||||||
# We track coverage only for the main module.
|
# We track coverage only for the main module.
|
||||||
MODULE_DIRS = . ./benchmarks ./zapgrpc/internal/test
|
MODULE_DIRS = . ./exp ./benchmarks ./zapgrpc/internal/test
|
||||||
|
|
||||||
# Many Go tools take file globs or directories as arguments instead of packages.
|
# Many Go tools take file globs or directories as arguments instead of packages.
|
||||||
GO_FILES := $(shell \
|
GO_FILES := $(shell \
|
||||||
|
|
@ -18,14 +19,15 @@ GO_FILES := $(shell \
|
||||||
all: lint test
|
all: lint test
|
||||||
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: $(GOLINT) $(STATICCHECK)
|
lint: $(REVIVE) $(STATICCHECK)
|
||||||
@rm -rf lint.log
|
@rm -rf lint.log
|
||||||
@echo "Checking formatting..."
|
@echo "Checking formatting..."
|
||||||
@gofmt -d -s $(GO_FILES) 2>&1 | tee lint.log
|
@gofmt -d -s $(GO_FILES) 2>&1 | tee lint.log
|
||||||
@echo "Checking vet..."
|
@echo "Checking vet..."
|
||||||
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go vet ./... 2>&1) &&) true | tee -a lint.log
|
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go vet ./... 2>&1) &&) true | tee -a lint.log
|
||||||
@echo "Checking lint..."
|
@echo "Checking lint..."
|
||||||
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && $(GOLINT) ./... 2>&1) &&) true | tee -a lint.log
|
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && \
|
||||||
|
$(REVIVE) -set_exit_status ./... 2>&1) &&) true | tee -a lint.log
|
||||||
@echo "Checking staticcheck..."
|
@echo "Checking staticcheck..."
|
||||||
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && $(STATICCHECK) ./... 2>&1) &&) true | tee -a lint.log
|
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && $(STATICCHECK) ./... 2>&1) &&) true | tee -a lint.log
|
||||||
@echo "Checking for unresolved FIXMEs..."
|
@echo "Checking for unresolved FIXMEs..."
|
||||||
|
|
@ -40,8 +42,11 @@ lint: $(GOLINT) $(STATICCHECK)
|
||||||
git --no-pager diff; \
|
git --no-pager diff; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$(GOLINT):
|
$(REVIVE):
|
||||||
cd tools && go install golang.org/x/lint/golint
|
cd tools && go install github.com/mgechev/revive
|
||||||
|
|
||||||
|
$(GOVULNCHECK):
|
||||||
|
cd tools && go install golang.org/x/vuln/cmd/govulncheck
|
||||||
|
|
||||||
$(STATICCHECK):
|
$(STATICCHECK):
|
||||||
cd tools && go install honnef.co/go/tools/cmd/staticcheck
|
cd tools && go install honnef.co/go/tools/cmd/staticcheck
|
||||||
|
|
@ -71,3 +76,7 @@ updatereadme:
|
||||||
.PHONY: tidy
|
.PHONY: tidy
|
||||||
tidy:
|
tidy:
|
||||||
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go mod tidy) &&) true
|
@$(foreach dir,$(MODULE_DIRS),(cd $(dir) && go mod tidy) &&) true
|
||||||
|
|
||||||
|
.PHONY: vulncheck
|
||||||
|
vulncheck: $(GOVULNCHECK)
|
||||||
|
$(GOVULNCHECK) ./...
|
||||||
|
|
@ -54,7 +54,7 @@ and make many small allocations. Put differently, using `encoding/json` and
|
||||||
Zap takes a different approach. It includes a reflection-free, zero-allocation
|
Zap takes a different approach. It includes a reflection-free, zero-allocation
|
||||||
JSON encoder, and the base `Logger` strives to avoid serialization overhead
|
JSON encoder, and the base `Logger` strives to avoid serialization overhead
|
||||||
and allocations wherever possible. By building the high-level `SugaredLogger`
|
and allocations wherever possible. By building the high-level `SugaredLogger`
|
||||||
on that foundation, zap lets users _choose_ when they need to count every
|
on that foundation, zap lets users *choose* when they need to count every
|
||||||
allocation and when they'd prefer a more familiar, loosely typed API.
|
allocation and when they'd prefer a more familiar, loosely typed API.
|
||||||
|
|
||||||
As measured by its own [benchmarking suite][], not only is zap more performant
|
As measured by its own [benchmarking suite][], not only is zap more performant
|
||||||
|
|
@ -64,40 +64,43 @@ id="anchor-versions">[1](#footnote-versions)</sup>
|
||||||
|
|
||||||
Log a message and 10 fields:
|
Log a message and 10 fields:
|
||||||
|
|
||||||
| Package | Time | Time % to zap | Objects Allocated |
|
| Package | Time | Time % to zap | Objects Allocated |
|
||||||
| :------------------ | :---------: | :-----------: | :---------------: |
|
| :------ | :--: | :-----------: | :---------------: |
|
||||||
| :zap: zap | 2900 ns/op | +0% | 5 allocs/op |
|
| :zap: zap | 1744 ns/op | +0% | 5 allocs/op
|
||||||
| :zap: zap (sugared) | 3475 ns/op | +20% | 10 allocs/op |
|
| :zap: zap (sugared) | 2483 ns/op | +42% | 10 allocs/op
|
||||||
| zerolog | 10639 ns/op | +267% | 32 allocs/op |
|
| zerolog | 918 ns/op | -47% | 1 allocs/op
|
||||||
| go-kit | 14434 ns/op | +398% | 59 allocs/op |
|
| go-kit | 5590 ns/op | +221% | 57 allocs/op
|
||||||
| logrus | 17104 ns/op | +490% | 81 allocs/op |
|
| slog | 5640 ns/op | +223% | 40 allocs/op
|
||||||
| apex/log | 32424 ns/op | +1018% | 66 allocs/op |
|
| apex/log | 21184 ns/op | +1115% | 63 allocs/op
|
||||||
| log15 | 33579 ns/op | +1058% | 76 allocs/op |
|
| logrus | 24338 ns/op | +1296% | 79 allocs/op
|
||||||
|
| log15 | 26054 ns/op | +1394% | 74 allocs/op
|
||||||
|
|
||||||
Log a message with a logger that already has 10 fields of context:
|
Log a message with a logger that already has 10 fields of context:
|
||||||
|
|
||||||
| Package | Time | Time % to zap | Objects Allocated |
|
| Package | Time | Time % to zap | Objects Allocated |
|
||||||
| :------------------ | :---------: | :-----------: | :---------------: |
|
| :------ | :--: | :-----------: | :---------------: |
|
||||||
| :zap: zap | 373 ns/op | +0% | 0 allocs/op |
|
| :zap: zap | 193 ns/op | +0% | 0 allocs/op
|
||||||
| :zap: zap (sugared) | 452 ns/op | +21% | 1 allocs/op |
|
| :zap: zap (sugared) | 227 ns/op | +18% | 1 allocs/op
|
||||||
| zerolog | 288 ns/op | -23% | 0 allocs/op |
|
| zerolog | 81 ns/op | -58% | 0 allocs/op
|
||||||
| go-kit | 11785 ns/op | +3060% | 58 allocs/op |
|
| slog | 322 ns/op | +67% | 0 allocs/op
|
||||||
| logrus | 19629 ns/op | +5162% | 70 allocs/op |
|
| go-kit | 5377 ns/op | +2686% | 56 allocs/op
|
||||||
| log15 | 21866 ns/op | +5762% | 72 allocs/op |
|
| apex/log | 19518 ns/op | +10013% | 53 allocs/op
|
||||||
| apex/log | 30890 ns/op | +8182% | 55 allocs/op |
|
| log15 | 19812 ns/op | +10165% | 70 allocs/op
|
||||||
|
| logrus | 21997 ns/op | +11297% | 68 allocs/op
|
||||||
|
|
||||||
Log a static string, without any context or `printf`-style templating:
|
Log a static string, without any context or `printf`-style templating:
|
||||||
|
|
||||||
| Package | Time | Time % to zap | Objects Allocated |
|
| Package | Time | Time % to zap | Objects Allocated |
|
||||||
| :------------------ | :--------: | :-----------: | :---------------: |
|
| :------ | :--: | :-----------: | :---------------: |
|
||||||
| :zap: zap | 381 ns/op | +0% | 0 allocs/op |
|
| :zap: zap | 165 ns/op | +0% | 0 allocs/op
|
||||||
| :zap: zap (sugared) | 410 ns/op | +8% | 1 allocs/op |
|
| :zap: zap (sugared) | 212 ns/op | +28% | 1 allocs/op
|
||||||
| zerolog | 369 ns/op | -3% | 0 allocs/op |
|
| zerolog | 95 ns/op | -42% | 0 allocs/op
|
||||||
| standard library | 385 ns/op | +1% | 2 allocs/op |
|
| slog | 296 ns/op | +79% | 0 allocs/op
|
||||||
| go-kit | 606 ns/op | +59% | 11 allocs/op |
|
| go-kit | 415 ns/op | +152% | 9 allocs/op
|
||||||
| logrus | 1730 ns/op | +354% | 25 allocs/op |
|
| standard library | 422 ns/op | +156% | 2 allocs/op
|
||||||
| apex/log | 1998 ns/op | +424% | 7 allocs/op |
|
| apex/log | 1601 ns/op | +870% | 5 allocs/op
|
||||||
| log15 | 4546 ns/op | +1093% | 22 allocs/op |
|
| logrus | 3017 ns/op | +1728% | 23 allocs/op
|
||||||
|
| log15 | 3469 ns/op | +2002% | 20 allocs/op
|
||||||
|
|
||||||
## Development Status: Stable
|
## Development Status: Stable
|
||||||
|
|
||||||
|
|
@ -131,3 +134,4 @@ pinned in the [benchmarks/go.mod][] file. [↩](#anchor-versions)
|
||||||
[cov]: https://codecov.io/gh/uber-go/zap
|
[cov]: https://codecov.io/gh/uber-go/zap
|
||||||
[benchmarking suite]: https://github.com/uber-go/zap/tree/master/benchmarks
|
[benchmarking suite]: https://github.com/uber-go/zap/tree/master/benchmarks
|
||||||
[benchmarks/go.mod]: https://github.com/uber-go/zap/blob/master/benchmarks/go.mod
|
[benchmarks/go.mod]: https://github.com/uber-go/zap/blob/master/benchmarks/go.mod
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,25 +20,29 @@
|
||||||
|
|
||||||
package buffer
|
package buffer
|
||||||
|
|
||||||
import "sync"
|
import (
|
||||||
|
"go.uber.org/zap/internal/pool"
|
||||||
|
)
|
||||||
|
|
||||||
// A Pool is a type-safe wrapper around a sync.Pool.
|
// A Pool is a type-safe wrapper around a sync.Pool.
|
||||||
type Pool struct {
|
type Pool struct {
|
||||||
p *sync.Pool
|
p *pool.Pool[*Buffer]
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewPool constructs a new Pool.
|
// NewPool constructs a new Pool.
|
||||||
func NewPool() Pool {
|
func NewPool() Pool {
|
||||||
return Pool{p: &sync.Pool{
|
return Pool{
|
||||||
New: func() interface{} {
|
p: pool.New(func() *Buffer {
|
||||||
return &Buffer{bs: make([]byte, 0, _size)}
|
return &Buffer{
|
||||||
},
|
bs: make([]byte, 0, _size),
|
||||||
}}
|
}
|
||||||
|
}),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get retrieves a Buffer from the pool, creating one if necessary.
|
// Get retrieves a Buffer from the pool, creating one if necessary.
|
||||||
func (p Pool) Get() *Buffer {
|
func (p Pool) Get() *Buffer {
|
||||||
buf := p.p.Get().(*Buffer)
|
buf := p.p.Get()
|
||||||
buf.Reset()
|
buf.Reset()
|
||||||
buf.pool = p
|
buf.pool = p
|
||||||
return buf
|
return buf
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,32 @@ type Config struct {
|
||||||
|
|
||||||
// NewProductionEncoderConfig returns an opinionated EncoderConfig for
|
// NewProductionEncoderConfig returns an opinionated EncoderConfig for
|
||||||
// production environments.
|
// production environments.
|
||||||
|
//
|
||||||
|
// Messages encoded with this configuration will be JSON-formatted
|
||||||
|
// and will have the following keys by default:
|
||||||
|
//
|
||||||
|
// - "level": The logging level (e.g. "info", "error").
|
||||||
|
// - "ts": The current time in number of seconds since the Unix epoch.
|
||||||
|
// - "msg": The message passed to the log statement.
|
||||||
|
// - "caller": If available, a short path to the file and line number
|
||||||
|
// where the log statement was issued.
|
||||||
|
// The logger configuration determines whether this field is captured.
|
||||||
|
// - "stacktrace": If available, a stack trace from the line
|
||||||
|
// where the log statement was issued.
|
||||||
|
// The logger configuration determines whether this field is captured.
|
||||||
|
//
|
||||||
|
// By default, the following formats are used for different types:
|
||||||
|
//
|
||||||
|
// - Time is formatted as floating-point number of seconds since the Unix
|
||||||
|
// epoch.
|
||||||
|
// - Duration is formatted as floating-point number of seconds.
|
||||||
|
//
|
||||||
|
// You may change these by setting the appropriate fields in the returned
|
||||||
|
// object.
|
||||||
|
// For example, use the following to change the time encoding format:
|
||||||
|
//
|
||||||
|
// cfg := zap.NewProductionEncoderConfig()
|
||||||
|
// cfg.EncodeTime = zapcore.ISO8601TimeEncoder
|
||||||
func NewProductionEncoderConfig() zapcore.EncoderConfig {
|
func NewProductionEncoderConfig() zapcore.EncoderConfig {
|
||||||
return zapcore.EncoderConfig{
|
return zapcore.EncoderConfig{
|
||||||
TimeKey: "ts",
|
TimeKey: "ts",
|
||||||
|
|
@ -112,11 +138,22 @@ func NewProductionEncoderConfig() zapcore.EncoderConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewProductionConfig is a reasonable production logging configuration.
|
// NewProductionConfig builds a reasonable default production logging
|
||||||
// Logging is enabled at InfoLevel and above.
|
// configuration.
|
||||||
|
// Logging is enabled at InfoLevel and above, and uses a JSON encoder.
|
||||||
|
// Logs are written to standard error.
|
||||||
|
// Stacktraces are included on logs of ErrorLevel and above.
|
||||||
|
// DPanicLevel logs will not panic, but will write a stacktrace.
|
||||||
//
|
//
|
||||||
// It uses a JSON encoder, writes to standard error, and enables sampling.
|
// Sampling is enabled at 100:100 by default,
|
||||||
// Stacktraces are automatically included on logs of ErrorLevel and above.
|
// meaning that after the first 100 log entries
|
||||||
|
// with the same level and message in the same second,
|
||||||
|
// it will log every 100th entry
|
||||||
|
// with the same level and message in the same second.
|
||||||
|
// You may disable this behavior by setting Sampling to nil.
|
||||||
|
//
|
||||||
|
// See [NewProductionEncoderConfig] for information
|
||||||
|
// on the default encoder configuration.
|
||||||
func NewProductionConfig() Config {
|
func NewProductionConfig() Config {
|
||||||
return Config{
|
return Config{
|
||||||
Level: NewAtomicLevelAt(InfoLevel),
|
Level: NewAtomicLevelAt(InfoLevel),
|
||||||
|
|
@ -134,6 +171,32 @@ func NewProductionConfig() Config {
|
||||||
|
|
||||||
// NewDevelopmentEncoderConfig returns an opinionated EncoderConfig for
|
// NewDevelopmentEncoderConfig returns an opinionated EncoderConfig for
|
||||||
// development environments.
|
// development environments.
|
||||||
|
//
|
||||||
|
// Messages encoded with this configuration will use Zap's console encoder
|
||||||
|
// intended to print human-readable output.
|
||||||
|
// It will print log messages with the following information:
|
||||||
|
//
|
||||||
|
// - The log level (e.g. "INFO", "ERROR").
|
||||||
|
// - The time in ISO8601 format (e.g. "2017-01-01T12:00:00Z").
|
||||||
|
// - The message passed to the log statement.
|
||||||
|
// - If available, a short path to the file and line number
|
||||||
|
// where the log statement was issued.
|
||||||
|
// The logger configuration determines whether this field is captured.
|
||||||
|
// - If available, a stacktrace from the line
|
||||||
|
// where the log statement was issued.
|
||||||
|
// The logger configuration determines whether this field is captured.
|
||||||
|
//
|
||||||
|
// By default, the following formats are used for different types:
|
||||||
|
//
|
||||||
|
// - Time is formatted in ISO8601 format (e.g. "2017-01-01T12:00:00Z").
|
||||||
|
// - Duration is formatted as a string (e.g. "1.234s").
|
||||||
|
//
|
||||||
|
// You may change these by setting the appropriate fields in the returned
|
||||||
|
// object.
|
||||||
|
// For example, use the following to change the time encoding format:
|
||||||
|
//
|
||||||
|
// cfg := zap.NewDevelopmentEncoderConfig()
|
||||||
|
// cfg.EncodeTime = zapcore.ISO8601TimeEncoder
|
||||||
func NewDevelopmentEncoderConfig() zapcore.EncoderConfig {
|
func NewDevelopmentEncoderConfig() zapcore.EncoderConfig {
|
||||||
return zapcore.EncoderConfig{
|
return zapcore.EncoderConfig{
|
||||||
// Keys can be anything except the empty string.
|
// Keys can be anything except the empty string.
|
||||||
|
|
@ -152,12 +215,15 @@ func NewDevelopmentEncoderConfig() zapcore.EncoderConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDevelopmentConfig is a reasonable development logging configuration.
|
// NewDevelopmentConfig builds a reasonable default development logging
|
||||||
// Logging is enabled at DebugLevel and above.
|
// configuration.
|
||||||
|
// Logging is enabled at DebugLevel and above, and uses a console encoder.
|
||||||
|
// Logs are written to standard error.
|
||||||
|
// Stacktraces are included on logs of WarnLevel and above.
|
||||||
|
// DPanicLevel logs will panic.
|
||||||
//
|
//
|
||||||
// It enables development mode (which makes DPanicLevel logs panic), uses a
|
// See [NewDevelopmentEncoderConfig] for information
|
||||||
// console encoder, writes to standard error, and disables sampling.
|
// on the default encoder configuration.
|
||||||
// Stacktraces are automatically included on logs of WarnLevel and above.
|
|
||||||
func NewDevelopmentConfig() Config {
|
func NewDevelopmentConfig() Config {
|
||||||
return Config{
|
return Config{
|
||||||
Level: NewAtomicLevelAt(DebugLevel),
|
Level: NewAtomicLevelAt(DebugLevel),
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,13 @@
|
||||||
package zap
|
package zap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"go.uber.org/zap/internal/pool"
|
||||||
|
|
||||||
"go.uber.org/zap/zapcore"
|
"go.uber.org/zap/zapcore"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _errArrayElemPool = sync.Pool{New: func() interface{} {
|
var _errArrayElemPool = pool.New(func() *errArrayElem {
|
||||||
return &errArrayElem{}
|
return &errArrayElem{}
|
||||||
}}
|
})
|
||||||
|
|
||||||
// Error is shorthand for the common idiom NamedError("error", err).
|
// Error is shorthand for the common idiom NamedError("error", err).
|
||||||
func Error(err error) Field {
|
func Error(err error) Field {
|
||||||
|
|
@ -60,7 +59,7 @@ func (errs errArray) MarshalLogArray(arr zapcore.ArrayEncoder) error {
|
||||||
// potentially an "errorVerbose" attribute, we need to wrap it in a
|
// potentially an "errorVerbose" attribute, we need to wrap it in a
|
||||||
// type that implements LogObjectMarshaler. To prevent this from
|
// type that implements LogObjectMarshaler. To prevent this from
|
||||||
// allocating, pool the wrapper type.
|
// allocating, pool the wrapper type.
|
||||||
elem := _errArrayElemPool.Get().(*errArrayElem)
|
elem := _errArrayElemPool.Get()
|
||||||
elem.error = errs[i]
|
elem.error = errs[i]
|
||||||
arr.AppendObject(elem)
|
arr.AppendObject(elem)
|
||||||
elem.error = nil
|
elem.error = nil
|
||||||
|
|
|
||||||
|
|
@ -410,6 +410,43 @@ func Inline(val zapcore.ObjectMarshaler) Field {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We discovered an issue where zap.Any can cause a performance degradation
|
||||||
|
// when used in new goroutines.
|
||||||
|
//
|
||||||
|
// This happens because the compiler assigns 4.8kb (one zap.Field per arm of
|
||||||
|
// switch statement) of stack space for zap.Any when it takes the form:
|
||||||
|
//
|
||||||
|
// switch v := v.(type) {
|
||||||
|
// case string:
|
||||||
|
// return String(key, v)
|
||||||
|
// case int:
|
||||||
|
// return Int(key, v)
|
||||||
|
// // ...
|
||||||
|
// default:
|
||||||
|
// return Reflect(key, v)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// To avoid this, we use the type switch to assign a value to a single local variable
|
||||||
|
// and then call a function on it.
|
||||||
|
// The local variable is just a function reference so it doesn't allocate
|
||||||
|
// when converted to an interface{}.
|
||||||
|
//
|
||||||
|
// A fair bit of experimentation went into this.
|
||||||
|
// See also:
|
||||||
|
//
|
||||||
|
// - https://github.com/uber-go/zap/pull/1301
|
||||||
|
// - https://github.com/uber-go/zap/pull/1303
|
||||||
|
// - https://github.com/uber-go/zap/pull/1304
|
||||||
|
// - https://github.com/uber-go/zap/pull/1305
|
||||||
|
// - https://github.com/uber-go/zap/pull/1308
|
||||||
|
type anyFieldC[T any] func(string, T) Field
|
||||||
|
|
||||||
|
func (f anyFieldC[T]) Any(key string, val any) Field {
|
||||||
|
v, _ := val.(T)
|
||||||
|
// val is guaranteed to be a T, except when it's nil.
|
||||||
|
return f(key, v)
|
||||||
|
}
|
||||||
|
|
||||||
// Any takes a key and an arbitrary value and chooses the best way to represent
|
// Any takes a key and an arbitrary value and chooses the best way to represent
|
||||||
// them as a field, falling back to a reflection-based approach only if
|
// them as a field, falling back to a reflection-based approach only if
|
||||||
// necessary.
|
// necessary.
|
||||||
|
|
@ -418,132 +455,136 @@ func Inline(val zapcore.ObjectMarshaler) Field {
|
||||||
// them. To minimize surprises, []byte values are treated as binary blobs, byte
|
// them. To minimize surprises, []byte values are treated as binary blobs, byte
|
||||||
// values are treated as uint8, and runes are always treated as integers.
|
// values are treated as uint8, and runes are always treated as integers.
|
||||||
func Any(key string, value interface{}) Field {
|
func Any(key string, value interface{}) Field {
|
||||||
switch val := value.(type) {
|
var c interface{ Any(string, any) Field }
|
||||||
|
|
||||||
|
switch value.(type) {
|
||||||
case zapcore.ObjectMarshaler:
|
case zapcore.ObjectMarshaler:
|
||||||
return Object(key, val)
|
c = anyFieldC[zapcore.ObjectMarshaler](Object)
|
||||||
case zapcore.ArrayMarshaler:
|
case zapcore.ArrayMarshaler:
|
||||||
return Array(key, val)
|
c = anyFieldC[zapcore.ArrayMarshaler](Array)
|
||||||
case bool:
|
case bool:
|
||||||
return Bool(key, val)
|
c = anyFieldC[bool](Bool)
|
||||||
case *bool:
|
case *bool:
|
||||||
return Boolp(key, val)
|
c = anyFieldC[*bool](Boolp)
|
||||||
case []bool:
|
case []bool:
|
||||||
return Bools(key, val)
|
c = anyFieldC[[]bool](Bools)
|
||||||
case complex128:
|
case complex128:
|
||||||
return Complex128(key, val)
|
c = anyFieldC[complex128](Complex128)
|
||||||
case *complex128:
|
case *complex128:
|
||||||
return Complex128p(key, val)
|
c = anyFieldC[*complex128](Complex128p)
|
||||||
case []complex128:
|
case []complex128:
|
||||||
return Complex128s(key, val)
|
c = anyFieldC[[]complex128](Complex128s)
|
||||||
case complex64:
|
case complex64:
|
||||||
return Complex64(key, val)
|
c = anyFieldC[complex64](Complex64)
|
||||||
case *complex64:
|
case *complex64:
|
||||||
return Complex64p(key, val)
|
c = anyFieldC[*complex64](Complex64p)
|
||||||
case []complex64:
|
case []complex64:
|
||||||
return Complex64s(key, val)
|
c = anyFieldC[[]complex64](Complex64s)
|
||||||
case float64:
|
case float64:
|
||||||
return Float64(key, val)
|
c = anyFieldC[float64](Float64)
|
||||||
case *float64:
|
case *float64:
|
||||||
return Float64p(key, val)
|
c = anyFieldC[*float64](Float64p)
|
||||||
case []float64:
|
case []float64:
|
||||||
return Float64s(key, val)
|
c = anyFieldC[[]float64](Float64s)
|
||||||
case float32:
|
case float32:
|
||||||
return Float32(key, val)
|
c = anyFieldC[float32](Float32)
|
||||||
case *float32:
|
case *float32:
|
||||||
return Float32p(key, val)
|
c = anyFieldC[*float32](Float32p)
|
||||||
case []float32:
|
case []float32:
|
||||||
return Float32s(key, val)
|
c = anyFieldC[[]float32](Float32s)
|
||||||
case int:
|
case int:
|
||||||
return Int(key, val)
|
c = anyFieldC[int](Int)
|
||||||
case *int:
|
case *int:
|
||||||
return Intp(key, val)
|
c = anyFieldC[*int](Intp)
|
||||||
case []int:
|
case []int:
|
||||||
return Ints(key, val)
|
c = anyFieldC[[]int](Ints)
|
||||||
case int64:
|
case int64:
|
||||||
return Int64(key, val)
|
c = anyFieldC[int64](Int64)
|
||||||
case *int64:
|
case *int64:
|
||||||
return Int64p(key, val)
|
c = anyFieldC[*int64](Int64p)
|
||||||
case []int64:
|
case []int64:
|
||||||
return Int64s(key, val)
|
c = anyFieldC[[]int64](Int64s)
|
||||||
case int32:
|
case int32:
|
||||||
return Int32(key, val)
|
c = anyFieldC[int32](Int32)
|
||||||
case *int32:
|
case *int32:
|
||||||
return Int32p(key, val)
|
c = anyFieldC[*int32](Int32p)
|
||||||
case []int32:
|
case []int32:
|
||||||
return Int32s(key, val)
|
c = anyFieldC[[]int32](Int32s)
|
||||||
case int16:
|
case int16:
|
||||||
return Int16(key, val)
|
c = anyFieldC[int16](Int16)
|
||||||
case *int16:
|
case *int16:
|
||||||
return Int16p(key, val)
|
c = anyFieldC[*int16](Int16p)
|
||||||
case []int16:
|
case []int16:
|
||||||
return Int16s(key, val)
|
c = anyFieldC[[]int16](Int16s)
|
||||||
case int8:
|
case int8:
|
||||||
return Int8(key, val)
|
c = anyFieldC[int8](Int8)
|
||||||
case *int8:
|
case *int8:
|
||||||
return Int8p(key, val)
|
c = anyFieldC[*int8](Int8p)
|
||||||
case []int8:
|
case []int8:
|
||||||
return Int8s(key, val)
|
c = anyFieldC[[]int8](Int8s)
|
||||||
case string:
|
case string:
|
||||||
return String(key, val)
|
c = anyFieldC[string](String)
|
||||||
case *string:
|
case *string:
|
||||||
return Stringp(key, val)
|
c = anyFieldC[*string](Stringp)
|
||||||
case []string:
|
case []string:
|
||||||
return Strings(key, val)
|
c = anyFieldC[[]string](Strings)
|
||||||
case uint:
|
case uint:
|
||||||
return Uint(key, val)
|
c = anyFieldC[uint](Uint)
|
||||||
case *uint:
|
case *uint:
|
||||||
return Uintp(key, val)
|
c = anyFieldC[*uint](Uintp)
|
||||||
case []uint:
|
case []uint:
|
||||||
return Uints(key, val)
|
c = anyFieldC[[]uint](Uints)
|
||||||
case uint64:
|
case uint64:
|
||||||
return Uint64(key, val)
|
c = anyFieldC[uint64](Uint64)
|
||||||
case *uint64:
|
case *uint64:
|
||||||
return Uint64p(key, val)
|
c = anyFieldC[*uint64](Uint64p)
|
||||||
case []uint64:
|
case []uint64:
|
||||||
return Uint64s(key, val)
|
c = anyFieldC[[]uint64](Uint64s)
|
||||||
case uint32:
|
case uint32:
|
||||||
return Uint32(key, val)
|
c = anyFieldC[uint32](Uint32)
|
||||||
case *uint32:
|
case *uint32:
|
||||||
return Uint32p(key, val)
|
c = anyFieldC[*uint32](Uint32p)
|
||||||
case []uint32:
|
case []uint32:
|
||||||
return Uint32s(key, val)
|
c = anyFieldC[[]uint32](Uint32s)
|
||||||
case uint16:
|
case uint16:
|
||||||
return Uint16(key, val)
|
c = anyFieldC[uint16](Uint16)
|
||||||
case *uint16:
|
case *uint16:
|
||||||
return Uint16p(key, val)
|
c = anyFieldC[*uint16](Uint16p)
|
||||||
case []uint16:
|
case []uint16:
|
||||||
return Uint16s(key, val)
|
c = anyFieldC[[]uint16](Uint16s)
|
||||||
case uint8:
|
case uint8:
|
||||||
return Uint8(key, val)
|
c = anyFieldC[uint8](Uint8)
|
||||||
case *uint8:
|
case *uint8:
|
||||||
return Uint8p(key, val)
|
c = anyFieldC[*uint8](Uint8p)
|
||||||
case []byte:
|
case []byte:
|
||||||
return Binary(key, val)
|
c = anyFieldC[[]byte](Binary)
|
||||||
case uintptr:
|
case uintptr:
|
||||||
return Uintptr(key, val)
|
c = anyFieldC[uintptr](Uintptr)
|
||||||
case *uintptr:
|
case *uintptr:
|
||||||
return Uintptrp(key, val)
|
c = anyFieldC[*uintptr](Uintptrp)
|
||||||
case []uintptr:
|
case []uintptr:
|
||||||
return Uintptrs(key, val)
|
c = anyFieldC[[]uintptr](Uintptrs)
|
||||||
case time.Time:
|
case time.Time:
|
||||||
return Time(key, val)
|
c = anyFieldC[time.Time](Time)
|
||||||
case *time.Time:
|
case *time.Time:
|
||||||
return Timep(key, val)
|
c = anyFieldC[*time.Time](Timep)
|
||||||
case []time.Time:
|
case []time.Time:
|
||||||
return Times(key, val)
|
c = anyFieldC[[]time.Time](Times)
|
||||||
case time.Duration:
|
case time.Duration:
|
||||||
return Duration(key, val)
|
c = anyFieldC[time.Duration](Duration)
|
||||||
case *time.Duration:
|
case *time.Duration:
|
||||||
return Durationp(key, val)
|
c = anyFieldC[*time.Duration](Durationp)
|
||||||
case []time.Duration:
|
case []time.Duration:
|
||||||
return Durations(key, val)
|
c = anyFieldC[[]time.Duration](Durations)
|
||||||
case error:
|
case error:
|
||||||
return NamedError(key, val)
|
c = anyFieldC[error](NamedError)
|
||||||
case []error:
|
case []error:
|
||||||
return Errors(key, val)
|
c = anyFieldC[[]error](Errors)
|
||||||
case fmt.Stringer:
|
case fmt.Stringer:
|
||||||
return Stringer(key, val)
|
c = anyFieldC[fmt.Stringer](Stringer)
|
||||||
default:
|
default:
|
||||||
return Reflect(key, val)
|
c = anyFieldC[any](Reflect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return c.Any(key, value)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
// Package internal and its subpackages hold types and functionality
|
||||||
|
// that are not part of Zap's public API.
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
import "go.uber.org/zap/zapcore"
|
import "go.uber.org/zap/zapcore"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
// Copyright (c) 2023 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
// Package pool provides internal pool utilities.
|
||||||
|
package pool
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Pool is a generic wrapper around [sync.Pool] to provide strongly-typed
|
||||||
|
// object pooling.
|
||||||
|
//
|
||||||
|
// Note that SA6002 (ref: https://staticcheck.io/docs/checks/#SA6002) will
|
||||||
|
// not be detected, so all internal pool use must take care to only store
|
||||||
|
// pointer types.
|
||||||
|
type Pool[T any] struct {
|
||||||
|
pool sync.Pool
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new [Pool] for T, and will use fn to construct new Ts when
|
||||||
|
// the pool is empty.
|
||||||
|
func New[T any](fn func() T) *Pool[T] {
|
||||||
|
return &Pool[T]{
|
||||||
|
pool: sync.Pool{
|
||||||
|
New: func() any {
|
||||||
|
return fn()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get gets a T from the pool, or creates a new one if the pool is empty.
|
||||||
|
func (p *Pool[T]) Get() T {
|
||||||
|
return p.pool.Get().(T)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put returns x into the pool.
|
||||||
|
func (p *Pool[T]) Put(x T) {
|
||||||
|
p.pool.Put(x)
|
||||||
|
}
|
||||||
|
|
@ -21,7 +21,8 @@
|
||||||
package zap
|
package zap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go.uber.org/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"go.uber.org/zap/internal"
|
"go.uber.org/zap/internal"
|
||||||
"go.uber.org/zap/zapcore"
|
"go.uber.org/zap/zapcore"
|
||||||
)
|
)
|
||||||
|
|
@ -76,9 +77,9 @@ var _ internal.LeveledEnabler = AtomicLevel{}
|
||||||
// NewAtomicLevel creates an AtomicLevel with InfoLevel and above logging
|
// NewAtomicLevel creates an AtomicLevel with InfoLevel and above logging
|
||||||
// enabled.
|
// enabled.
|
||||||
func NewAtomicLevel() AtomicLevel {
|
func NewAtomicLevel() AtomicLevel {
|
||||||
return AtomicLevel{
|
lvl := AtomicLevel{l: new(atomic.Int32)}
|
||||||
l: atomic.NewInt32(int32(InfoLevel)),
|
lvl.l.Store(int32(InfoLevel))
|
||||||
}
|
return lvl
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAtomicLevelAt is a convenience function that creates an AtomicLevel
|
// NewAtomicLevelAt is a convenience function that creates an AtomicLevel
|
||||||
|
|
|
||||||
|
|
@ -281,6 +281,12 @@ func (log *Logger) Core() zapcore.Core {
|
||||||
return log.core
|
return log.core
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Name returns the Logger's underlying name,
|
||||||
|
// or an empty string if the logger is unnamed.
|
||||||
|
func (log *Logger) Name() string {
|
||||||
|
return log.name
|
||||||
|
}
|
||||||
|
|
||||||
func (log *Logger) clone() *Logger {
|
func (log *Logger) clone() *Logger {
|
||||||
copy := *log
|
copy := *log
|
||||||
return ©
|
return ©
|
||||||
|
|
|
||||||
|
|
@ -22,19 +22,17 @@ package zap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"go.uber.org/zap/buffer"
|
"go.uber.org/zap/buffer"
|
||||||
"go.uber.org/zap/internal/bufferpool"
|
"go.uber.org/zap/internal/bufferpool"
|
||||||
|
"go.uber.org/zap/internal/pool"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _stacktracePool = sync.Pool{
|
var _stacktracePool = pool.New(func() *stacktrace {
|
||||||
New: func() interface{} {
|
return &stacktrace{
|
||||||
return &stacktrace{
|
storage: make([]uintptr, 64),
|
||||||
storage: make([]uintptr, 64),
|
}
|
||||||
}
|
})
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
type stacktrace struct {
|
type stacktrace struct {
|
||||||
pcs []uintptr // program counters; always a subslice of storage
|
pcs []uintptr // program counters; always a subslice of storage
|
||||||
|
|
@ -68,7 +66,7 @@ const (
|
||||||
//
|
//
|
||||||
// The caller must call Free on the returned stacktrace after using it.
|
// The caller must call Free on the returned stacktrace after using it.
|
||||||
func captureStacktrace(skip int, depth stacktraceDepth) *stacktrace {
|
func captureStacktrace(skip int, depth stacktraceDepth) *stacktrace {
|
||||||
stack := _stacktracePool.Get().(*stacktrace)
|
stack := _stacktracePool.Get()
|
||||||
|
|
||||||
switch depth {
|
switch depth {
|
||||||
case stacktraceFirst:
|
case stacktraceFirst:
|
||||||
|
|
|
||||||
|
|
@ -122,74 +122,88 @@ func (s *SugaredLogger) Level() zapcore.Level {
|
||||||
return zapcore.LevelOf(s.base.core)
|
return zapcore.LevelOf(s.base.core)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug uses fmt.Sprint to construct and log a message.
|
// Debug logs the provided arguments at [DebugLevel].
|
||||||
|
// Spaces are added between arguments when neither is a string.
|
||||||
func (s *SugaredLogger) Debug(args ...interface{}) {
|
func (s *SugaredLogger) Debug(args ...interface{}) {
|
||||||
s.log(DebugLevel, "", args, nil)
|
s.log(DebugLevel, "", args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info uses fmt.Sprint to construct and log a message.
|
// Info logs the provided arguments at [InfoLevel].
|
||||||
|
// Spaces are added between arguments when neither is a string.
|
||||||
func (s *SugaredLogger) Info(args ...interface{}) {
|
func (s *SugaredLogger) Info(args ...interface{}) {
|
||||||
s.log(InfoLevel, "", args, nil)
|
s.log(InfoLevel, "", args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn uses fmt.Sprint to construct and log a message.
|
// Warn logs the provided arguments at [WarnLevel].
|
||||||
|
// Spaces are added between arguments when neither is a string.
|
||||||
func (s *SugaredLogger) Warn(args ...interface{}) {
|
func (s *SugaredLogger) Warn(args ...interface{}) {
|
||||||
s.log(WarnLevel, "", args, nil)
|
s.log(WarnLevel, "", args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error uses fmt.Sprint to construct and log a message.
|
// Error logs the provided arguments at [ErrorLevel].
|
||||||
|
// Spaces are added between arguments when neither is a string.
|
||||||
func (s *SugaredLogger) Error(args ...interface{}) {
|
func (s *SugaredLogger) Error(args ...interface{}) {
|
||||||
s.log(ErrorLevel, "", args, nil)
|
s.log(ErrorLevel, "", args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DPanic uses fmt.Sprint to construct and log a message. In development, the
|
// DPanic logs the provided arguments at [DPanicLevel].
|
||||||
// logger then panics. (See DPanicLevel for details.)
|
// In development, the logger then panics. (See [DPanicLevel] for details.)
|
||||||
|
// Spaces are added between arguments when neither is a string.
|
||||||
func (s *SugaredLogger) DPanic(args ...interface{}) {
|
func (s *SugaredLogger) DPanic(args ...interface{}) {
|
||||||
s.log(DPanicLevel, "", args, nil)
|
s.log(DPanicLevel, "", args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Panic uses fmt.Sprint to construct and log a message, then panics.
|
// Panic constructs a message with the provided arguments and panics.
|
||||||
|
// Spaces are added between arguments when neither is a string.
|
||||||
func (s *SugaredLogger) Panic(args ...interface{}) {
|
func (s *SugaredLogger) Panic(args ...interface{}) {
|
||||||
s.log(PanicLevel, "", args, nil)
|
s.log(PanicLevel, "", args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fatal uses fmt.Sprint to construct and log a message, then calls os.Exit.
|
// Fatal constructs a message with the provided arguments and calls os.Exit.
|
||||||
|
// Spaces are added between arguments when neither is a string.
|
||||||
func (s *SugaredLogger) Fatal(args ...interface{}) {
|
func (s *SugaredLogger) Fatal(args ...interface{}) {
|
||||||
s.log(FatalLevel, "", args, nil)
|
s.log(FatalLevel, "", args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debugf uses fmt.Sprintf to log a templated message.
|
// Debugf formats the message according to the format specifier
|
||||||
|
// and logs it at [DebugLevel].
|
||||||
func (s *SugaredLogger) Debugf(template string, args ...interface{}) {
|
func (s *SugaredLogger) Debugf(template string, args ...interface{}) {
|
||||||
s.log(DebugLevel, template, args, nil)
|
s.log(DebugLevel, template, args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Infof uses fmt.Sprintf to log a templated message.
|
// Infof formats the message according to the format specifier
|
||||||
|
// and logs it at [InfoLevel].
|
||||||
func (s *SugaredLogger) Infof(template string, args ...interface{}) {
|
func (s *SugaredLogger) Infof(template string, args ...interface{}) {
|
||||||
s.log(InfoLevel, template, args, nil)
|
s.log(InfoLevel, template, args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warnf uses fmt.Sprintf to log a templated message.
|
// Warnf formats the message according to the format specifier
|
||||||
|
// and logs it at [WarnLevel].
|
||||||
func (s *SugaredLogger) Warnf(template string, args ...interface{}) {
|
func (s *SugaredLogger) Warnf(template string, args ...interface{}) {
|
||||||
s.log(WarnLevel, template, args, nil)
|
s.log(WarnLevel, template, args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Errorf uses fmt.Sprintf to log a templated message.
|
// Errorf formats the message according to the format specifier
|
||||||
|
// and logs it at [ErrorLevel].
|
||||||
func (s *SugaredLogger) Errorf(template string, args ...interface{}) {
|
func (s *SugaredLogger) Errorf(template string, args ...interface{}) {
|
||||||
s.log(ErrorLevel, template, args, nil)
|
s.log(ErrorLevel, template, args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DPanicf uses fmt.Sprintf to log a templated message. In development, the
|
// DPanicf formats the message according to the format specifier
|
||||||
// logger then panics. (See DPanicLevel for details.)
|
// and logs it at [DPanicLevel].
|
||||||
|
// In development, the logger then panics. (See [DPanicLevel] for details.)
|
||||||
func (s *SugaredLogger) DPanicf(template string, args ...interface{}) {
|
func (s *SugaredLogger) DPanicf(template string, args ...interface{}) {
|
||||||
s.log(DPanicLevel, template, args, nil)
|
s.log(DPanicLevel, template, args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Panicf uses fmt.Sprintf to log a templated message, then panics.
|
// Panicf formats the message according to the format specifier
|
||||||
|
// and panics.
|
||||||
func (s *SugaredLogger) Panicf(template string, args ...interface{}) {
|
func (s *SugaredLogger) Panicf(template string, args ...interface{}) {
|
||||||
s.log(PanicLevel, template, args, nil)
|
s.log(PanicLevel, template, args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fatalf uses fmt.Sprintf to log a templated message, then calls os.Exit.
|
// Fatalf formats the message according to the format specifier
|
||||||
|
// and calls os.Exit.
|
||||||
func (s *SugaredLogger) Fatalf(template string, args ...interface{}) {
|
func (s *SugaredLogger) Fatalf(template string, args ...interface{}) {
|
||||||
s.log(FatalLevel, template, args, nil)
|
s.log(FatalLevel, template, args, nil)
|
||||||
}
|
}
|
||||||
|
|
@ -241,38 +255,45 @@ func (s *SugaredLogger) Fatalw(msg string, keysAndValues ...interface{}) {
|
||||||
s.log(FatalLevel, msg, nil, keysAndValues)
|
s.log(FatalLevel, msg, nil, keysAndValues)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debugln uses fmt.Sprintln to construct and log a message.
|
// Debugln logs a message at [DebugLevel].
|
||||||
|
// Spaces are always added between arguments.
|
||||||
func (s *SugaredLogger) Debugln(args ...interface{}) {
|
func (s *SugaredLogger) Debugln(args ...interface{}) {
|
||||||
s.logln(DebugLevel, args, nil)
|
s.logln(DebugLevel, args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Infoln uses fmt.Sprintln to construct and log a message.
|
// Infoln logs a message at [InfoLevel].
|
||||||
|
// Spaces are always added between arguments.
|
||||||
func (s *SugaredLogger) Infoln(args ...interface{}) {
|
func (s *SugaredLogger) Infoln(args ...interface{}) {
|
||||||
s.logln(InfoLevel, args, nil)
|
s.logln(InfoLevel, args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warnln uses fmt.Sprintln to construct and log a message.
|
// Warnln logs a message at [WarnLevel].
|
||||||
|
// Spaces are always added between arguments.
|
||||||
func (s *SugaredLogger) Warnln(args ...interface{}) {
|
func (s *SugaredLogger) Warnln(args ...interface{}) {
|
||||||
s.logln(WarnLevel, args, nil)
|
s.logln(WarnLevel, args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Errorln uses fmt.Sprintln to construct and log a message.
|
// Errorln logs a message at [ErrorLevel].
|
||||||
|
// Spaces are always added between arguments.
|
||||||
func (s *SugaredLogger) Errorln(args ...interface{}) {
|
func (s *SugaredLogger) Errorln(args ...interface{}) {
|
||||||
s.logln(ErrorLevel, args, nil)
|
s.logln(ErrorLevel, args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DPanicln uses fmt.Sprintln to construct and log a message. In development, the
|
// DPanicln logs a message at [DPanicLevel].
|
||||||
// logger then panics. (See DPanicLevel for details.)
|
// In development, the logger then panics. (See [DPanicLevel] for details.)
|
||||||
|
// Spaces are always added between arguments.
|
||||||
func (s *SugaredLogger) DPanicln(args ...interface{}) {
|
func (s *SugaredLogger) DPanicln(args ...interface{}) {
|
||||||
s.logln(DPanicLevel, args, nil)
|
s.logln(DPanicLevel, args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Panicln uses fmt.Sprintln to construct and log a message, then panics.
|
// Panicln logs a message at [PanicLevel] and panics.
|
||||||
|
// Spaces are always added between arguments.
|
||||||
func (s *SugaredLogger) Panicln(args ...interface{}) {
|
func (s *SugaredLogger) Panicln(args ...interface{}) {
|
||||||
s.logln(PanicLevel, args, nil)
|
s.logln(PanicLevel, args, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fatalln uses fmt.Sprintln to construct and log a message, then calls os.Exit.
|
// Fatalln logs a message at [FatalLevel] and calls os.Exit.
|
||||||
|
// Spaces are always added between arguments.
|
||||||
func (s *SugaredLogger) Fatalln(args ...interface{}) {
|
func (s *SugaredLogger) Fatalln(args ...interface{}) {
|
||||||
s.logln(FatalLevel, args, nil)
|
s.logln(FatalLevel, args, nil)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,20 +22,20 @@ package zapcore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"go.uber.org/zap/buffer"
|
"go.uber.org/zap/buffer"
|
||||||
"go.uber.org/zap/internal/bufferpool"
|
"go.uber.org/zap/internal/bufferpool"
|
||||||
|
"go.uber.org/zap/internal/pool"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _sliceEncoderPool = sync.Pool{
|
var _sliceEncoderPool = pool.New(func() *sliceArrayEncoder {
|
||||||
New: func() interface{} {
|
return &sliceArrayEncoder{
|
||||||
return &sliceArrayEncoder{elems: make([]interface{}, 0, 2)}
|
elems: make([]interface{}, 0, 2),
|
||||||
},
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
func getSliceEncoder() *sliceArrayEncoder {
|
func getSliceEncoder() *sliceArrayEncoder {
|
||||||
return _sliceEncoderPool.Get().(*sliceArrayEncoder)
|
return _sliceEncoderPool.Get()
|
||||||
}
|
}
|
||||||
|
|
||||||
func putSliceEncoder(e *sliceArrayEncoder) {
|
func putSliceEncoder(e *sliceArrayEncoder) {
|
||||||
|
|
|
||||||
|
|
@ -24,25 +24,23 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.uber.org/multierr"
|
"go.uber.org/multierr"
|
||||||
"go.uber.org/zap/internal/bufferpool"
|
"go.uber.org/zap/internal/bufferpool"
|
||||||
"go.uber.org/zap/internal/exit"
|
"go.uber.org/zap/internal/exit"
|
||||||
|
"go.uber.org/zap/internal/pool"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var _cePool = pool.New(func() *CheckedEntry {
|
||||||
_cePool = sync.Pool{New: func() interface{} {
|
// Pre-allocate some space for cores.
|
||||||
// Pre-allocate some space for cores.
|
return &CheckedEntry{
|
||||||
return &CheckedEntry{
|
cores: make([]Core, 4),
|
||||||
cores: make([]Core, 4),
|
}
|
||||||
}
|
})
|
||||||
}}
|
|
||||||
)
|
|
||||||
|
|
||||||
func getCheckedEntry() *CheckedEntry {
|
func getCheckedEntry() *CheckedEntry {
|
||||||
ce := _cePool.Get().(*CheckedEntry)
|
ce := _cePool.Get()
|
||||||
ce.reset()
|
ce.reset()
|
||||||
return ce
|
return ce
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,8 @@ package zapcore
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
|
||||||
|
"go.uber.org/zap/internal/pool"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Encodes the given error into fields of an object. A field with the given
|
// Encodes the given error into fields of an object. A field with the given
|
||||||
|
|
@ -103,9 +104,9 @@ func (errs errArray) MarshalLogArray(arr ArrayEncoder) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var _errArrayElemPool = sync.Pool{New: func() interface{} {
|
var _errArrayElemPool = pool.New(func() *errArrayElem {
|
||||||
return &errArrayElem{}
|
return &errArrayElem{}
|
||||||
}}
|
})
|
||||||
|
|
||||||
// Encodes any error into a {"error": ...} re-using the same errors logic.
|
// Encodes any error into a {"error": ...} re-using the same errors logic.
|
||||||
//
|
//
|
||||||
|
|
@ -113,7 +114,7 @@ var _errArrayElemPool = sync.Pool{New: func() interface{} {
|
||||||
type errArrayElem struct{ err error }
|
type errArrayElem struct{ err error }
|
||||||
|
|
||||||
func newErrArrayElem(err error) *errArrayElem {
|
func newErrArrayElem(err error) *errArrayElem {
|
||||||
e := _errArrayElemPool.Get().(*errArrayElem)
|
e := _errArrayElemPool.Get()
|
||||||
e.err = err
|
e.err = err
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,24 +23,20 @@ package zapcore
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"math"
|
"math"
|
||||||
"sync"
|
|
||||||
"time"
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"go.uber.org/zap/buffer"
|
"go.uber.org/zap/buffer"
|
||||||
"go.uber.org/zap/internal/bufferpool"
|
"go.uber.org/zap/internal/bufferpool"
|
||||||
|
"go.uber.org/zap/internal/pool"
|
||||||
)
|
)
|
||||||
|
|
||||||
// For JSON-escaping; see jsonEncoder.safeAddString below.
|
// For JSON-escaping; see jsonEncoder.safeAddString below.
|
||||||
const _hex = "0123456789abcdef"
|
const _hex = "0123456789abcdef"
|
||||||
|
|
||||||
var _jsonPool = sync.Pool{New: func() interface{} {
|
var _jsonPool = pool.New(func() *jsonEncoder {
|
||||||
return &jsonEncoder{}
|
return &jsonEncoder{}
|
||||||
}}
|
})
|
||||||
|
|
||||||
func getJSONEncoder() *jsonEncoder {
|
|
||||||
return _jsonPool.Get().(*jsonEncoder)
|
|
||||||
}
|
|
||||||
|
|
||||||
func putJSONEncoder(enc *jsonEncoder) {
|
func putJSONEncoder(enc *jsonEncoder) {
|
||||||
if enc.reflectBuf != nil {
|
if enc.reflectBuf != nil {
|
||||||
|
|
@ -354,7 +350,7 @@ func (enc *jsonEncoder) Clone() Encoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (enc *jsonEncoder) clone() *jsonEncoder {
|
func (enc *jsonEncoder) clone() *jsonEncoder {
|
||||||
clone := getJSONEncoder()
|
clone := _jsonPool.Get()
|
||||||
clone.EncoderConfig = enc.EncoderConfig
|
clone.EncoderConfig = enc.EncoderConfig
|
||||||
clone.spaced = enc.spaced
|
clone.spaced = enc.spaced
|
||||||
clone.openNamespaces = enc.openNamespaces
|
clone.openNamespaces = enc.openNamespaces
|
||||||
|
|
@ -527,7 +523,7 @@ func (enc *jsonEncoder) tryAddRuneSelf(b byte) bool {
|
||||||
if b >= utf8.RuneSelf {
|
if b >= utf8.RuneSelf {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if 0x20 <= b && b != '\\' && b != '"' {
|
if b >= 0x20 && b != '\\' && b != '"' {
|
||||||
enc.buf.AppendByte(b)
|
enc.buf.AppendByte(b)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,8 @@
|
||||||
package zapcore
|
package zapcore
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"go.uber.org/atomic"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -66,16 +65,16 @@ func (c *counter) IncCheckReset(t time.Time, tick time.Duration) uint64 {
|
||||||
tn := t.UnixNano()
|
tn := t.UnixNano()
|
||||||
resetAfter := c.resetAt.Load()
|
resetAfter := c.resetAt.Load()
|
||||||
if resetAfter > tn {
|
if resetAfter > tn {
|
||||||
return c.counter.Inc()
|
return c.counter.Add(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.counter.Store(1)
|
c.counter.Store(1)
|
||||||
|
|
||||||
newResetAfter := tn + tick.Nanoseconds()
|
newResetAfter := tn + tick.Nanoseconds()
|
||||||
if !c.resetAt.CAS(resetAfter, newResetAfter) {
|
if !c.resetAt.CompareAndSwap(resetAfter, newResetAfter) {
|
||||||
// We raced with another goroutine trying to reset, and it also reset
|
// We raced with another goroutine trying to reset, and it also reset
|
||||||
// the counter to 1, so we need to reincrement the counter.
|
// the counter to 1, so we need to reincrement the counter.
|
||||||
return c.counter.Inc()
|
return c.counter.Add(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,10 @@ func (e Flags) IsDisabledTransportEncryption() bool {
|
||||||
return e != nil && e[TransportEncryption] == Disabled
|
return e != nil && e[TransportEncryption] == Disabled
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e Flags) IsOIDCAuthentication() bool {
|
||||||
|
return e != nil && e[OIDCAuthentication] == Enabled
|
||||||
|
}
|
||||||
|
|
||||||
func (e Flags) String() string {
|
func (e Flags) String() string {
|
||||||
return fmt.Sprintf("%+v", map[string]Flag(e))
|
return fmt.Sprintf("%+v", map[string]Flag(e))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,4 +24,5 @@ const (
|
||||||
NewTriggerFilters = "new-trigger-filters"
|
NewTriggerFilters = "new-trigger-filters"
|
||||||
TransportEncryption = "transport-encryption"
|
TransportEncryption = "transport-encryption"
|
||||||
EvenTypeAutoCreate = "eventtype-auto-create"
|
EvenTypeAutoCreate = "eventtype-auto-create"
|
||||||
|
OIDCAuthentication = "authentication.oidc"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,6 @@
|
||||||
|
|
||||||
source "$(dirname "${BASH_SOURCE[0]:-$0}")/infra-library.sh"
|
source "$(dirname "${BASH_SOURCE[0]:-$0}")/infra-library.sh"
|
||||||
|
|
||||||
readonly TEST_RESULT_FILE=/tmp/${REPO_NAME}-e2e-result
|
|
||||||
|
|
||||||
# Tear down the test resources.
|
# Tear down the test resources.
|
||||||
function teardown_test_resources() {
|
function teardown_test_resources() {
|
||||||
header "Tearing down test environment"
|
header "Tearing down test environment"
|
||||||
|
|
@ -133,6 +131,7 @@ E2E_SCRIPT=""
|
||||||
function initialize() {
|
function initialize() {
|
||||||
local run_tests=0
|
local run_tests=0
|
||||||
local custom_flags=()
|
local custom_flags=()
|
||||||
|
local extra_gcloud_flags=()
|
||||||
local parse_script_flags=0
|
local parse_script_flags=0
|
||||||
E2E_SCRIPT="$(get_canonical_path "$0")"
|
E2E_SCRIPT="$(get_canonical_path "$0")"
|
||||||
local e2e_script_command=( "${E2E_SCRIPT}" "--run-tests" )
|
local e2e_script_command=( "${E2E_SCRIPT}" "--run-tests" )
|
||||||
|
|
@ -177,16 +176,12 @@ function initialize() {
|
||||||
shift
|
shift
|
||||||
done
|
done
|
||||||
|
|
||||||
if [[ "${CLOUD_PROVIDER}" == "gke" ]]; then
|
|
||||||
custom_flags+=("--addons=NodeLocalDNS")
|
|
||||||
fi
|
|
||||||
|
|
||||||
readonly SKIP_DUMP_ON_FAILURE
|
readonly SKIP_DUMP_ON_FAILURE
|
||||||
readonly TEARDOWN
|
readonly TEARDOWN
|
||||||
readonly CLOUD_PROVIDER
|
readonly CLOUD_PROVIDER
|
||||||
|
|
||||||
if (( ! run_tests )); then
|
if (( ! run_tests )); then
|
||||||
create_test_cluster "${CLOUD_PROVIDER}" custom_flags e2e_script_command
|
create_test_cluster "${CLOUD_PROVIDER}" custom_flags extra_gcloud_flags e2e_script_command
|
||||||
else
|
else
|
||||||
setup_test_cluster
|
setup_test_cluster
|
||||||
fi
|
fi
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ function create_test_cluster() {
|
||||||
fi
|
fi
|
||||||
|
|
||||||
case "$1" in
|
case "$1" in
|
||||||
gke) create_gke_test_cluster "$2" "$3" "${4:-}" ;;
|
gke) create_gke_test_cluster "$2" "$3" "$4" "${5:-}" ;;
|
||||||
kind) create_kind_test_cluster "$2" "$3" "${4:-}" ;;
|
kind) create_kind_test_cluster "$2" "$3" "${4:-}" ;;
|
||||||
*) echo "unsupported provider: $1"; exit 1 ;;
|
*) echo "unsupported provider: $1"; exit 1 ;;
|
||||||
esac
|
esac
|
||||||
|
|
@ -117,29 +117,50 @@ function create_kind_test_cluster() {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create a GKE test cluster with kubetest2 and run the test command.
|
# Create a GKE test cluster with kubetest2 and run the test command.
|
||||||
# Parameters: $1 - custom flags defined in kntest
|
# Parameters: $1 - custom flags defined in kubetest2
|
||||||
# $2 - test command to run after the cluster is created (optional)
|
# $2 - custom flags to pass directly to gcloud
|
||||||
|
# $3 - test command to run after the cluster is created (optional)
|
||||||
function create_gke_test_cluster() {
|
function create_gke_test_cluster() {
|
||||||
local -n _custom_flags=$1
|
local -n _custom_flags=$1
|
||||||
local -n _test_command=$2
|
local -n _extra_gcloud_flags=$2
|
||||||
|
local -n _test_command=$3
|
||||||
|
|
||||||
# We are disabling logs and metrics on Boskos Clusters by default as they are not used. Manually set ENABLE_GKE_TELEMETRY to true to enable telemetry
|
# We are disabling logs and metrics on Boskos Clusters by default as they are not used. Manually set ENABLE_GKE_TELEMETRY to true to enable telemetry
|
||||||
# and ENABLE_PREEMPTIBLE_NODES to true to create preemptible/spot VMs. VM Preemption is a rare event and shouldn't be distruptive given the fault tolerant nature of our tests.
|
# and ENABLE_PREEMPTIBLE_NODES to true to create preemptible/spot VMs. VM Preemption is a rare event and shouldn't be distruptive given the fault tolerant nature of our tests.
|
||||||
local extra_gcloud_flags=""
|
|
||||||
if [[ "${ENABLE_GKE_TELEMETRY:-}" != "true" ]]; then
|
if [[ "${ENABLE_GKE_TELEMETRY:-}" != "true" ]]; then
|
||||||
extra_gcloud_flags="${extra_gcloud_flags} --logging=NONE --monitoring=NONE"
|
_extra_gcloud_flags+=("--logging=NONE --monitoring=NONE")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${CLOUD_PROVIDER}" == "gke" ]]; then
|
||||||
|
extra_gcloud_flags+=("--addons=NodeLocalDNS")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ "${ENABLE_PREEMPTIBLE_NODES:-}" == "true" ]]; then
|
if [[ "${ENABLE_PREEMPTIBLE_NODES:-}" == "true" ]]; then
|
||||||
extra_gcloud_flags="${extra_gcloud_flags} --preemptible"
|
_extra_gcloud_flags+=("--preemptible")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_extra_gcloud_flags+=("--quiet")
|
||||||
if ! command -v kubetest2 >/dev/null; then
|
if ! command -v kubetest2 >/dev/null; then
|
||||||
tmpbin="$(mktemp -d)"
|
tmpbin="$(mktemp -d)"
|
||||||
echo "kubetest2 not found, installing in temp path: ${tmpbin}"
|
echo "kubetest2 not found, installing in temp path: ${tmpbin}"
|
||||||
GOBIN="$tmpbin" go install sigs.k8s.io/kubetest2/...@latest
|
GOBIN="$tmpbin" go install sigs.k8s.io/kubetest2/...@latest
|
||||||
export PATH="${tmpbin}:${PATH}"
|
export PATH="${tmpbin}:${PATH}"
|
||||||
fi
|
fi
|
||||||
run_kntest kubetest2 gke "${_custom_flags[@]}" \
|
if [[ ! " ${_custom_flags[*]} " =~ "--machine-type=" ]]; then
|
||||||
--test-command="${_test_command[*]}" \
|
_custom_flags+=("--machine-type=e2-standard-4")
|
||||||
--extra-gcloud-flags="${extra_gcloud_flags}"
|
fi
|
||||||
|
kubetest2 gke "${_custom_flags[@]}" \
|
||||||
|
--rundir-in-artifacts \
|
||||||
|
--up \
|
||||||
|
--down \
|
||||||
|
--boskos-heartbeat-interval-seconds=20 \
|
||||||
|
--v=1 \
|
||||||
|
--network=e2e-network \
|
||||||
|
--boskos-acquire-timeout-seconds=1200 \
|
||||||
|
--region="${E2E_CLUSTER_REGION},us-east1,us-west1" \
|
||||||
|
--gcloud-extra-flags="${_extra_gcloud_flags[*]}" \
|
||||||
|
--retryable-error-patterns='.*does not have enough resources available to fulfill.*,.*only \\d+ nodes out of \\d+ have registered; this is likely due to Nodes failing to start correctly.*,.*All cluster resources were brought up.+ but: component .+ from endpoint .+ is unhealthy.*' \
|
||||||
|
--test=exec \
|
||||||
|
-- \
|
||||||
|
"${_test_command[@]}"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
# This is a helper script for Knative performance test scripts.
|
# This is a helper script for Knative performance test scripts.
|
||||||
# See README.md for instructions on how to use it.
|
# See README.md for instructions on how to use it.
|
||||||
|
|
||||||
source $(dirname "${BASH_SOURCE[0]}")/library.sh
|
source "$(dirname "${BASH_SOURCE[0]}")"/library.sh
|
||||||
|
|
||||||
# Configurable parameters.
|
# Configurable parameters.
|
||||||
# If not provided, they will fall back to the default values.
|
# If not provided, they will fall back to the default values.
|
||||||
|
|
@ -76,7 +76,8 @@ EOF
|
||||||
update_knative || abort "failed to update knative"
|
update_knative || abort "failed to update knative"
|
||||||
fi
|
fi
|
||||||
# get benchmark name from the cluster name
|
# get benchmark name from the cluster name
|
||||||
local benchmark_name=$(get_benchmark_name "$1")
|
local benchmark_name
|
||||||
|
benchmark_name=$(get_benchmark_name "$1")
|
||||||
if function_exists update_benchmark; then
|
if function_exists update_benchmark; then
|
||||||
update_benchmark "${benchmark_name}" || abort "failed to update benchmark"
|
update_benchmark "${benchmark_name}" || abort "failed to update benchmark"
|
||||||
fi
|
fi
|
||||||
|
|
@ -92,13 +93,16 @@ function get_benchmark_name() {
|
||||||
# Update the clusters related to the current repo.
|
# Update the clusters related to the current repo.
|
||||||
function update_clusters() {
|
function update_clusters() {
|
||||||
header "Updating all clusters for ${REPO_NAME}"
|
header "Updating all clusters for ${REPO_NAME}"
|
||||||
local all_clusters=$(gcloud container clusters list --project="${PROJECT_NAME}" --format="csv[no-heading](name,zone)")
|
local all_clusters
|
||||||
|
all_clusters=$(gcloud container clusters list --project="${PROJECT_NAME}" --format="csv[no-heading](name,zone)")
|
||||||
echo ">> Project contains clusters:" "${all_clusters}"
|
echo ">> Project contains clusters:" "${all_clusters}"
|
||||||
for cluster in ${all_clusters}; do
|
for cluster in ${all_clusters}; do
|
||||||
local name=$(echo "${cluster}" | cut -f1 -d",")
|
local name
|
||||||
|
name=$(echo "${cluster}" | cut -f1 -d",")
|
||||||
# the cluster name is prefixed with "${REPO_NAME}--", here we should only handle clusters belonged to the current repo
|
# the cluster name is prefixed with "${REPO_NAME}--", here we should only handle clusters belonged to the current repo
|
||||||
[[ ! ${name} =~ ^${REPO_NAME}-- ]] && continue
|
[[ ! ${name} =~ ^${REPO_NAME}-- ]] && continue
|
||||||
local zone=$(echo "${cluster}" | cut -f2 -d",")
|
local zone
|
||||||
|
zone=$(echo "${cluster}" | cut -f2 -d",")
|
||||||
|
|
||||||
# Update all resources installed on the cluster
|
# Update all resources installed on the cluster
|
||||||
update_cluster "${name}" "${zone}"
|
update_cluster "${name}" "${zone}"
|
||||||
|
|
@ -109,7 +113,7 @@ function update_clusters() {
|
||||||
# Run the perf-tests tool
|
# Run the perf-tests tool
|
||||||
# Parameters: $1..$n - parameters passed to the tool
|
# Parameters: $1..$n - parameters passed to the tool
|
||||||
function run_perf_cluster_tool() {
|
function run_perf_cluster_tool() {
|
||||||
perf-tests $@
|
perf-tests "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Delete the old clusters belonged to the current repo, and recreate them with the same configuration.
|
# Delete the old clusters belonged to the current repo, and recreate them with the same configuration.
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
# This is a helper script for Knative presubmit test scripts.
|
# This is a helper script for Knative presubmit test scripts.
|
||||||
# See README.md for instructions on how to use it.
|
# See README.md for instructions on how to use it.
|
||||||
|
|
||||||
source $(dirname "${BASH_SOURCE[0]}")/library.sh
|
source "$(dirname "${BASH_SOURCE[0]}")"/library.sh
|
||||||
|
|
||||||
# Custom configuration of presubmit tests
|
# Custom configuration of presubmit tests
|
||||||
readonly PRESUBMIT_TEST_FAIL_FAST=${PRESUBMIT_TEST_FAIL_FAST:-0}
|
readonly PRESUBMIT_TEST_FAIL_FAST=${PRESUBMIT_TEST_FAIL_FAST:-0}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
source $(dirname $0)/e2e-common.sh
|
source $(dirname "$0")/e2e-common.sh
|
||||||
|
|
||||||
function setup_auto_tls_env_variables() {
|
function setup_auto_tls_env_variables() {
|
||||||
# DNS zone for the testing domain.
|
# DNS zone for the testing domain.
|
||||||
|
|
@ -92,12 +92,12 @@ function setup_http01_auto_tls() {
|
||||||
|
|
||||||
if [[ -z "${MESH}" ]]; then
|
if [[ -z "${MESH}" ]]; then
|
||||||
echo "Install cert-manager no-mesh ClusterIssuer"
|
echo "Install cert-manager no-mesh ClusterIssuer"
|
||||||
kubectl apply -f ${E2E_YAML_DIR}/test/config/autotls/certmanager/http01/issuer.yaml
|
kubectl apply -f "${E2E_YAML_DIR}"/test/config/autotls/certmanager/http01/issuer.yaml
|
||||||
else
|
else
|
||||||
echo "Install cert-manager mesh ClusterIssuer"
|
echo "Install cert-manager mesh ClusterIssuer"
|
||||||
kubectl apply -f ${E2E_YAML_DIR}/test/config/autotls/certmanager/http01/mesh-issuer.yaml
|
kubectl apply -f "${E2E_YAML_DIR}"/test/config/autotls/certmanager/http01/mesh-issuer.yaml
|
||||||
fi
|
fi
|
||||||
kubectl apply -f ${E2E_YAML_DIR}/test/config/autotls/certmanager/http01/config-certmanager.yaml
|
kubectl apply -f "${E2E_YAML_DIR}"/test/config/autotls/certmanager/http01/config-certmanager.yaml
|
||||||
setup_dns_record
|
setup_dns_record
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -159,7 +159,7 @@ function delete_dns_record() {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Script entry point.
|
# Script entry point.
|
||||||
initialize "$@" --skip-istio-addon --min-nodes=4 --max-nodes=4 --enable-ha --cluster-version=1.25
|
initialize "$@" --num-nodes=4 --enable-ha --cluster-version=1.25
|
||||||
|
|
||||||
# Run the tests
|
# Run the tests
|
||||||
header "Running tests"
|
header "Running tests"
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@
|
||||||
source $(dirname $0)/e2e-common.sh
|
source $(dirname $0)/e2e-common.sh
|
||||||
|
|
||||||
# Script entry point.
|
# Script entry point.
|
||||||
initialize --skip-istio-addon --min-nodes=4 --max-nodes=4 --enable-ha --cluster-version=1.25 "$@"
|
initialize --num-nodes=4 --enable-ha --cluster-version=1.25 "$@"
|
||||||
|
|
||||||
# Run the tests
|
# Run the tests
|
||||||
header "Running tests"
|
header "Running tests"
|
||||||
|
|
@ -45,7 +45,7 @@ fi
|
||||||
if (( HTTPS )); then
|
if (( HTTPS )); then
|
||||||
use_https="--https"
|
use_https="--https"
|
||||||
toggle_feature autoTLS Enabled config-network
|
toggle_feature autoTLS Enabled config-network
|
||||||
kubectl apply -f ${E2E_YAML_DIR}/test/config/autotls/certmanager/caissuer/
|
kubectl apply -f "${E2E_YAML_DIR}"/test/config/autotls/certmanager/caissuer/
|
||||||
add_trap "kubectl delete -f ${E2E_YAML_DIR}/test/config/autotls/certmanager/caissuer/ --ignore-not-found" SIGKILL SIGTERM SIGQUIT
|
add_trap "kubectl delete -f ${E2E_YAML_DIR}/test/config/autotls/certmanager/caissuer/ --ignore-not-found" SIGKILL SIGTERM SIGQUIT
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
@ -79,7 +79,7 @@ go_test_e2e -timeout=30m \
|
||||||
./test/conformance/api/... \
|
./test/conformance/api/... \
|
||||||
./test/conformance/runtime/... \
|
./test/conformance/runtime/... \
|
||||||
./test/e2e \
|
./test/e2e \
|
||||||
${parallelism} \
|
"${parallelism}" \
|
||||||
${TEST_OPTIONS} || failed=1
|
${TEST_OPTIONS} || failed=1
|
||||||
toggle_feature autocreateClusterDomainClaims false config-network || fail_test
|
toggle_feature autocreateClusterDomainClaims false config-network || fail_test
|
||||||
|
|
||||||
|
|
@ -95,11 +95,11 @@ toggle_feature autocreateClusterDomainClaims true config-network || fail_test
|
||||||
go_test_e2e -timeout=2m ./test/e2e/domainmapping ${TEST_OPTIONS} || failed=1
|
go_test_e2e -timeout=2m ./test/e2e/domainmapping ${TEST_OPTIONS} || failed=1
|
||||||
toggle_feature autocreateClusterDomainClaims false config-network || fail_test
|
toggle_feature autocreateClusterDomainClaims false config-network || fail_test
|
||||||
|
|
||||||
kubectl get cm "config-gc" -n "${SYSTEM_NAMESPACE}" -o yaml > ${TMP_DIR}/config-gc.yaml
|
kubectl get cm "config-gc" -n "${SYSTEM_NAMESPACE}" -o yaml > "${TMP_DIR}"/config-gc.yaml
|
||||||
add_trap "kubectl replace cm 'config-gc' -n ${SYSTEM_NAMESPACE} -f ${TMP_DIR}/config-gc.yaml" SIGKILL SIGTERM SIGQUIT
|
add_trap "kubectl replace cm 'config-gc' -n ${SYSTEM_NAMESPACE} -f ${TMP_DIR}/config-gc.yaml" SIGKILL SIGTERM SIGQUIT
|
||||||
immediate_gc
|
immediate_gc
|
||||||
go_test_e2e -timeout=2m ./test/e2e/gc ${TEST_OPTIONS} || failed=1
|
go_test_e2e -timeout=2m ./test/e2e/gc ${TEST_OPTIONS} || failed=1
|
||||||
kubectl replace cm "config-gc" -n ${SYSTEM_NAMESPACE} -f ${TMP_DIR}/config-gc.yaml
|
kubectl replace cm "config-gc" -n ${SYSTEM_NAMESPACE} -f "${TMP_DIR}"/config-gc.yaml
|
||||||
|
|
||||||
# Run scale tests.
|
# Run scale tests.
|
||||||
# Note that we use a very high -parallel because each ksvc is run as its own
|
# Note that we use a very high -parallel because each ksvc is run as its own
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ function stage_test_resources() {
|
||||||
# Skip installing istio as an add-on.
|
# Skip installing istio as an add-on.
|
||||||
# Skip installing a pvc as it is not used in upgrade tests
|
# Skip installing a pvc as it is not used in upgrade tests
|
||||||
# Skip installing a resource quota as it is not used in upgrade tests
|
# Skip installing a resource quota as it is not used in upgrade tests
|
||||||
PVC=0 QUOTA=0 initialize "$@" --skip-istio-addon --min-nodes=4 --max-nodes=4 --cluster-version=1.25 \
|
PVC=0 QUOTA=0 initialize "$@" --num-nodes=4 --cluster-version=1.25 \
|
||||||
--install-latest-release
|
--install-latest-release
|
||||||
|
|
||||||
# TODO(#2656): Reduce the timeout after we get this test to consistently passing.
|
# TODO(#2656): Reduce the timeout after we get this test to consistently passing.
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ github.com/gregjones/httpcache
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule
|
github.com/grpc-ecosystem/grpc-gateway/v2/internal/httprule
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2/runtime
|
github.com/grpc-ecosystem/grpc-gateway/v2/runtime
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2/utilities
|
github.com/grpc-ecosystem/grpc-gateway/v2/utilities
|
||||||
# github.com/hashicorp/golang-lru v0.5.4
|
# github.com/hashicorp/golang-lru v1.0.2
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/hashicorp/golang-lru
|
github.com/hashicorp/golang-lru
|
||||||
github.com/hashicorp/golang-lru/simplelru
|
github.com/hashicorp/golang-lru/simplelru
|
||||||
|
|
@ -333,10 +333,10 @@ go.starlark.net/syntax
|
||||||
# go.uber.org/atomic v1.10.0
|
# go.uber.org/atomic v1.10.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
go.uber.org/atomic
|
go.uber.org/atomic
|
||||||
# go.uber.org/multierr v1.8.0
|
# go.uber.org/multierr v1.10.0
|
||||||
## explicit; go 1.14
|
## explicit; go 1.19
|
||||||
go.uber.org/multierr
|
go.uber.org/multierr
|
||||||
# go.uber.org/zap v1.24.0
|
# go.uber.org/zap v1.25.0
|
||||||
## explicit; go 1.19
|
## explicit; go 1.19
|
||||||
go.uber.org/zap
|
go.uber.org/zap
|
||||||
go.uber.org/zap/buffer
|
go.uber.org/zap/buffer
|
||||||
|
|
@ -344,6 +344,7 @@ go.uber.org/zap/internal
|
||||||
go.uber.org/zap/internal/bufferpool
|
go.uber.org/zap/internal/bufferpool
|
||||||
go.uber.org/zap/internal/color
|
go.uber.org/zap/internal/color
|
||||||
go.uber.org/zap/internal/exit
|
go.uber.org/zap/internal/exit
|
||||||
|
go.uber.org/zap/internal/pool
|
||||||
go.uber.org/zap/zapcore
|
go.uber.org/zap/zapcore
|
||||||
# golang.org/x/mod v0.12.0
|
# golang.org/x/mod v0.12.0
|
||||||
## explicit; go 1.17
|
## explicit; go 1.17
|
||||||
|
|
@ -410,7 +411,7 @@ golang.org/x/tools/internal/typeparams
|
||||||
# gomodules.xyz/jsonpatch/v2 v2.3.0
|
# gomodules.xyz/jsonpatch/v2 v2.3.0
|
||||||
## explicit; go 1.20
|
## explicit; go 1.20
|
||||||
gomodules.xyz/jsonpatch/v2
|
gomodules.xyz/jsonpatch/v2
|
||||||
# google.golang.org/api v0.136.0
|
# google.golang.org/api v0.138.0
|
||||||
## explicit; go 1.19
|
## explicit; go 1.19
|
||||||
google.golang.org/api/support/bundler
|
google.golang.org/api/support/bundler
|
||||||
# google.golang.org/appengine v1.6.7
|
# google.golang.org/appengine v1.6.7
|
||||||
|
|
@ -939,10 +940,10 @@ k8s.io/utils/net
|
||||||
k8s.io/utils/pointer
|
k8s.io/utils/pointer
|
||||||
k8s.io/utils/strings/slices
|
k8s.io/utils/strings/slices
|
||||||
k8s.io/utils/trace
|
k8s.io/utils/trace
|
||||||
# knative.dev/client-pkg v0.0.0-20230809014238-38d2dc0dd50a
|
# knative.dev/client-pkg v0.0.0-20230815131440-5abd12981b4b
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
knative.dev/client-pkg/pkg/kn/plugin
|
knative.dev/client-pkg/pkg/kn/plugin
|
||||||
# knative.dev/eventing v0.38.1-0.20230815095940-29ac3eee64a4
|
# knative.dev/eventing v0.38.1-0.20230822134255-a2e2aa3d515d
|
||||||
## explicit; go 1.19
|
## explicit; go 1.19
|
||||||
knative.dev/eventing/pkg/apis/config
|
knative.dev/eventing/pkg/apis/config
|
||||||
knative.dev/eventing/pkg/apis/duck
|
knative.dev/eventing/pkg/apis/duck
|
||||||
|
|
@ -971,10 +972,10 @@ knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1
|
||||||
knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1/fake
|
knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1/fake
|
||||||
knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1beta2
|
knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1beta2
|
||||||
knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1beta2/fake
|
knative.dev/eventing/pkg/client/clientset/versioned/typed/sources/v1beta2/fake
|
||||||
# knative.dev/hack v0.0.0-20230815012940-044c02b7a447
|
# knative.dev/hack v0.0.0-20230818155117-9cc05a31e8c0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
knative.dev/hack
|
knative.dev/hack
|
||||||
# knative.dev/networking v0.0.0-20230817140742-4bfcc9fb6012
|
# knative.dev/networking v0.0.0-20230822003854-1d7920d27b9e
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
knative.dev/networking/pkg
|
knative.dev/networking/pkg
|
||||||
knative.dev/networking/pkg/apis/networking
|
knative.dev/networking/pkg/apis/networking
|
||||||
|
|
@ -989,7 +990,7 @@ knative.dev/networking/pkg/http/probe
|
||||||
knative.dev/networking/pkg/http/proxy
|
knative.dev/networking/pkg/http/proxy
|
||||||
knative.dev/networking/pkg/http/stats
|
knative.dev/networking/pkg/http/stats
|
||||||
knative.dev/networking/pkg/k8s
|
knative.dev/networking/pkg/k8s
|
||||||
# knative.dev/pkg v0.0.0-20230815132840-4f651e092853
|
# knative.dev/pkg v0.0.0-20230821102121-81e4ee140363
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
knative.dev/pkg/apis
|
knative.dev/pkg/apis
|
||||||
knative.dev/pkg/apis/duck
|
knative.dev/pkg/apis/duck
|
||||||
|
|
@ -1039,7 +1040,7 @@ knative.dev/pkg/tracing/config
|
||||||
knative.dev/pkg/tracing/propagation
|
knative.dev/pkg/tracing/propagation
|
||||||
knative.dev/pkg/tracing/propagation/tracecontextb3
|
knative.dev/pkg/tracing/propagation/tracecontextb3
|
||||||
knative.dev/pkg/tracker
|
knative.dev/pkg/tracker
|
||||||
# knative.dev/serving v0.38.1-0.20230818202718-e9425f8d5260
|
# knative.dev/serving v0.38.1-0.20230823024257-eaff0b39b99e
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
knative.dev/serving/pkg/apis/autoscaling
|
knative.dev/serving/pkg/apis/autoscaling
|
||||||
knative.dev/serving/pkg/apis/autoscaling/v1alpha1
|
knative.dev/serving/pkg/apis/autoscaling/v1alpha1
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue