Repository: knative/pkg
Pull request #2777 (2023-08-02 01:12:55)

Use go sync/atomic instead of go.uber.org/atomic
Since Go 1.19, new type for sync/atomic was introduced like Int32 and Bool so it is possible to replace `go.uber.org/atomic`.

This patch makes the change.

**Release Note**

```release-note
NONE
```

knative-prow[bot]: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by: *<a href="https://github.com/knative/pkg/pull/2777#" title="Author self-approved">nak3</a>*
**Once this PR has been reviewed and has the lgtm label**, please assign [pierdipi](https://github.com/pierdipi) for approval. For more information see [the Kubernetes Code Review Process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process).

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=knative%2Fpkg).

<details open>
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/knative/pkg/blob/main/OWNERS)~~ [nak3]
- **[apis/duck/OWNERS](https://github.com/knative/pkg/blob/main/apis/duck/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["pierdipi"]} -->
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/knative/pkg/pull/2777?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) Report
Patch coverage: **`100.00%`** and project coverage change: **`+0.03%`** :tada:
> Comparison is base [(`7b50f3c`)](https://app.codecov.io/gh/knative/pkg/commit/7b50f3c433ae4a86ca2be0d829e23e5eb0031c18?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) 81.75% compared to head [(`f6dcc59`)](https://app.codecov.io/gh/knative/pkg/pull/2777?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) 81.79%.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #2777      +/-   ##
==========================================
+ Coverage   81.75%   81.79%   +0.03%     
==========================================
  Files         167      167              
  Lines       10201    10204       +3     
==========================================
+ Hits         8340     8346       +6     
+ Misses       1614     1612       -2     
+ Partials      247      246       -1     
```


| [Files Changed](https://app.codecov.io/gh/knative/pkg/pull/2777?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative) | Coverage Δ | |
|---|---|---|
| [metrics/metrics.go](https://app.codecov.io/gh/knative/pkg/pull/2777?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative#diff-bWV0cmljcy9tZXRyaWNzLmdv) | `83.33% <100.00%> (ø)` | |
| [profiling/server.go](https://app.codecov.io/gh/knative/pkg/pull/2777?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative#diff-cHJvZmlsaW5nL3NlcnZlci5nbw==) | `75.92% <100.00%> (+1.41%)` | :arrow_up: |

... and [1 file with indirect coverage changes](https://app.codecov.io/gh/knative/pkg/pull/2777/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative)


</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/knative/pkg/pull/2777?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative).


Patch:
diff --git a/.github/workflows/knative-downstream.yaml b/.github/workflows/knative-downstream.yaml
index 3bbb6fe03..fc952625c 100644
--- a/.github/workflows/knative-downstream.yaml
+++ b/.github/workflows/knative-downstream.yaml
@@ -31,20 +31,20 @@ jobs:
           - knative/eventing
           - knative/operator
           - knative/client
-          - knative-sandbox/eventing-autoscaler-keda
-          - knative-sandbox/eventing-ceph
-          - knative-sandbox/eventing-github
-          - knative-sandbox/eventing-gitlab
-          - knative-sandbox/eventing-kafka
-          - knative-sandbox/eventing-kafka-broker
-          - knative-sandbox/eventing-rabbitmq
-          - knative-sandbox/eventing-redis
-          - knative-sandbox/kn-plugin-admin
-          - knative-sandbox/net-certmanager
-          - knative-sandbox/net-contour
-          - knative-sandbox/net-http01
-          - knative-sandbox/net-istio
-          - knative-sandbox/net-kourier
+          - knative-extensions/eventing-autoscaler-keda
+          - knative-extensions/eventing-ceph
+          - knative-extensions/eventing-github
+          - knative-extensions/eventing-gitlab
+          - knative-extensions/eventing-kafka
+          - knative-extensions/eventing-kafka-broker
+          - knative-extensions/eventing-rabbitmq
+          - knative-extensions/eventing-redis
+          - knative-extensions/kn-plugin-admin
+          - knative-extensions/net-certmanager
+          - knative-extensions/net-contour
+          - knative-extensions/net-http01
+          - knative-extensions/net-istio
+          - knative-extensions/net-kourier
 
     runs-on: ubuntu-latest
 
diff --git a/.github/workflows/knative-go-build.yaml b/.github/workflows/knative-go-build.yaml
index 0ecbdbccb..10c3de1a1 100644
--- a/.github/workflows/knative-go-build.yaml
+++ b/.github/workflows/knative-go-build.yaml
@@ -1,7 +1,7 @@
 # Copyright 2020 The Knative Authors.
 # SPDX-License-Identifier: Apache-2.0
 
-# This file is automagically synced here from github.com/knative-sandbox/knobots
+# This file is automagically synced here from github.com/knative-extensions/knobots
 
 name: Build
 
diff --git a/.github/workflows/knative-security.yaml b/.github/workflows/knative-security.yaml
index 4a0848ca6..a6cd68137 100644
--- a/.github/workflows/knative-security.yaml
+++ b/.github/workflows/knative-security.yaml
@@ -1,7 +1,7 @@
 # Copyright 2020 The Knative Authors.
 # SPDX-License-Identifier: Apache-2.0
 
-# This file is automagically synced here from github.com/knative-sandbox/knobots
+# This file is automagically synced here from github.com/knative-extensions/knobots
 
 name: 'Security'
 
diff --git a/.github/workflows/knative-stale.yaml b/.github/workflows/knative-stale.yaml
index e46461c1e..2e25b9d99 100644
--- a/.github/workflows/knative-stale.yaml
+++ b/.github/workflows/knative-stale.yaml
@@ -1,7 +1,7 @@
 # Copyright 2020 The Knative Authors.
 # SPDX-License-Identifier: Apache-2.0
 
-# This file is automagically synced here from github.com/knative-sandbox/knobots
+# This file is automagically synced here from github.com/knative-extensions/knobots
 name: 'Close stale'
 
 on:
diff --git a/.github/workflows/knative-style.yaml b/.github/workflows/knative-style.yaml
index 7ca9e6024..55bb1537c 100644
--- a/.github/workflows/knative-style.yaml
+++ b/.github/workflows/knative-style.yaml
@@ -1,7 +1,7 @@
 # Copyright 2020 The Knative Authors.
 # SPDX-License-Identifier: Apache-2.0
 
-# This file is automagically synced here from github.com/knative-sandbox/knobots
+# This file is automagically synced here from github.com/knative-extensions/knobots
 
 name: Code Style
 
diff --git a/.github/workflows/knative-verify.yaml b/.github/workflows/knative-verify.yaml
index 28a4af54b..e1a28c4f5 100644
--- a/.github/workflows/knative-verify.yaml
+++ b/.github/workflows/knative-verify.yaml
@@ -12,8 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# This file is automagically synced here from github.com/knative-sandbox/.github
-# repo by knobots: https://github.com/knative-sandbox/knobots and will be overwritten.
+# This file is automagically synced here from github.com/knative-extensions/.github
+# repo by knobots: https://github.com/knative-extensions/knobots and will be overwritten.
 
 name: Verify
 
diff --git a/go.mod b/go.mod
index fa17d03a6..ed3f7efad 100644
--- a/go.mod
+++ b/go.mod
@@ -20,7 +20,7 @@ require (
 	github.com/google/gofuzz v1.2.0
 	github.com/google/mako v0.0.0-20190821191249-122f8dcef9e3
 	github.com/google/uuid v1.3.0
-	github.com/gorilla/websocket v1.4.2
+	github.com/gorilla/websocket v1.5.0
 	github.com/hashicorp/golang-lru v0.5.4
 	github.com/kelseyhightower/envconfig v1.4.0
 	github.com/openzipkin/zipkin-go v0.3.0
@@ -29,9 +29,8 @@ require (
 	github.com/spf13/pflag v1.0.5
 	github.com/tsenart/vegeta/v12 v12.11.0
 	go.opencensus.io v0.24.0
-	go.uber.org/atomic v1.9.0
 	go.uber.org/automaxprocs v1.4.0
-	go.uber.org/zap v1.19.1
+	go.uber.org/zap v1.24.0
 	golang.org/x/net v0.12.0
 	golang.org/x/oauth2 v0.8.0
 	golang.org/x/sync v0.3.0
@@ -57,6 +56,7 @@ require (
 	cloud.google.com/go v0.110.2 // indirect
 	cloud.google.com/go/compute v1.19.0 // indirect
 	cloud.google.com/go/iam v1.0.1 // indirect
+	github.com/benbjohnson/clock v1.1.0 // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 	github.com/emicklei/go-restful/v3 v3.9.0 // indirect
@@ -90,6 +90,7 @@ require (
 	github.com/prometheus/procfs v0.10.1 // indirect
 	github.com/prometheus/statsd_exporter v0.21.0 // indirect
 	github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 // indirect
+	go.uber.org/atomic v1.9.0 // indirect
 	go.uber.org/goleak v1.2.0 // indirect
 	go.uber.org/multierr v1.6.0 // indirect
 	golang.org/x/crypto v0.11.0 // indirect
diff --git a/go.sum b/go.sum
index efd4f73bf..8018aba58 100644
--- a/go.sum
+++ b/go.sum
@@ -239,8 +239,8 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z
 github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
 github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
 github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
-github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
-github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
+github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw=
 github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
 github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3 h1:lLT7ZLSzGLI08vc9cpd+tYmNWjdKDqyr/2L+f6U12Fk=
@@ -409,7 +409,6 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
@@ -426,15 +425,14 @@ go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
 go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 go.uber.org/automaxprocs v1.4.0 h1:CpDZl6aOlLhReez+8S3eEotD7Jx0Os++lemPlMULQP0=
 go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q=
-go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
 go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
 go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
-go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
-go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
+go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
+go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
 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-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -479,7 +477,6 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
 golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
 golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
@@ -517,7 +514,6 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
 golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@@ -543,7 +539,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
 golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
@@ -587,9 +582,7 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -661,7 +654,6 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
 golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
 golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
 golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 golang.org/x/tools v0.11.0 h1:EMCa6U9S2LtZXLAMoWiR/R8dAQFRqbAitmbJ2UKhoi8=
 golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
diff --git a/metrics/metrics.go b/metrics/metrics.go
index 453e1b84a..b65f470cc 100644
--- a/metrics/metrics.go
+++ b/metrics/metrics.go
@@ -19,12 +19,12 @@ package metrics
 import (
 	"context"
 	"net/url"
+	"sync/atomic"
 	"time"
 
 	"go.opencensus.io/stats"
 	"go.opencensus.io/stats/view"
 	"go.opencensus.io/tag"
-	"go.uber.org/atomic"
 	"k8s.io/client-go/tools/cache"
 	"k8s.io/client-go/tools/metrics"
 	"k8s.io/client-go/util/workqueue"
@@ -74,13 +74,13 @@ var _ workqueue.GaugeMetric = (*gaugeMetric)(nil)
 
 // Inc implements CounterMetric
 func (m *gaugeMetric) Inc() {
-	total := m.total.Inc()
+	total := m.total.Add(1)
 	Record(context.Background(), m.measure.M(total), stats.WithTags(m.mutators...))
 }
 
 // Dec implements GaugeMetric
 func (m *gaugeMetric) Dec() {
-	total := m.total.Dec()
+	total := m.total.Add(-1)
 	Record(context.Background(), m.measure.M(total), stats.WithTags(m.mutators...))
 }
 
diff --git a/profiling/server.go b/profiling/server.go
index 36e08b4b4..f362f36fa 100644
--- a/profiling/server.go
+++ b/profiling/server.go
@@ -22,9 +22,9 @@ import (
 	"net/http/pprof"
 	"os"
 	"strconv"
+	"sync/atomic"
 	"time"
 
-	"go.uber.org/atomic"
 	"go.uber.org/zap"
 	corev1 "k8s.io/api/core/v1"
 )
@@ -63,8 +63,11 @@ func NewHandler(logger *zap.SugaredLogger, enableProfiling bool) *Handler {
 	mux.HandleFunc(pprofPrefix+"trace", pprof.Trace)
 
 	logger.Info("Profiling enabled: ", enableProfiling)
+	var enabled atomic.Bool
+	enabled.Store(enableProfiling)
+
 	return &Handler{
-		enabled: atomic.NewBool(enableProfiling),
+		enabled: &enabled,
 		handler: mux,
 		log:     logger,
 	}
diff --git a/third_party/VENDOR-LICENSE/github.com/benbjohnson/clock/LICENSE b/third_party/VENDOR-LICENSE/github.com/benbjohnson/clock/LICENSE
new file mode 100644
index 000000000..ce212cb1c
--- /dev/null
+++ b/third_party/VENDOR-LICENSE/github.com/benbjohnson/clock/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Ben Johnson
+
+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.
diff --git a/vendor/github.com/benbjohnson/clock/LICENSE b/vendor/github.com/benbjohnson/clock/LICENSE
new file mode 100644
index 000000000..ce212cb1c
--- /dev/null
+++ b/vendor/github.com/benbjohnson/clock/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014 Ben Johnson
+
+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.
diff --git a/vendor/github.com/benbjohnson/clock/README.md b/vendor/github.com/benbjohnson/clock/README.md
new file mode 100644
index 000000000..ee37dfe1b
--- /dev/null
+++ b/vendor/github.com/benbjohnson/clock/README.md
@@ -0,0 +1,104 @@
+clock
+=====
+
+Clock is a small library for mocking time in Go. It provides an interface
+around the standard library's [`time`][time] package so that the application
+can use the realtime clock while tests can use the mock clock.
+
+[time]: http://golang.org/pkg/time/
+
+
+## Usage
+
+### Realtime Clock
+
+Your application can maintain a `Clock` variable that will allow realtime and
+mock clocks to be interchangeable. For example, if you had an `Application` type:
+
+```go
+import "github.com/benbjohnson/clock"
+
+type Application struct {
+	Clock clock.Clock
+}
+```
+
+You could initialize it to use the realtime clock like this:
+
+```go
+var app Application
+app.Clock = clock.New()
+...
+```
+
+Then all timers and time-related functionality should be performed from the
+`Clock` variable.
+
+
+### Mocking time
+
+In your tests, you will want to use a `Mock` clock:
+
+```go
+import (
+	"testing"
+
+	"github.com/benbjohnson/clock"
+)
+
+func TestApplication_DoSomething(t *testing.T) {
+	mock := clock.NewMock()
+	app := Application{Clock: mock}
+	...
+}
+```
+
+Now that you've initialized your application to use the mock clock, you can
+adjust the time programmatically. The mock clock always starts from the Unix
+epoch (midnight UTC on Jan 1, 1970).
+
+
+### Controlling time
+
+The mock clock provides the same functions that the standard library's `time`
+package provides. For example, to find the current time, you use the `Now()`
+function:
+
+```go
+mock := clock.NewMock()
+
+// Find the current time.
+mock.Now().UTC() // 1970-01-01 00:00:00 +0000 UTC
+
+// Move the clock forward.
+mock.Add(2 * time.Hour)
+
+// Check the time again. It's 2 hours later!
+mock.Now().UTC() // 1970-01-01 02:00:00 +0000 UTC
+```
+
+Timers and Tickers are also controlled by this same mock clock. They will only
+execute when the clock is moved forward:
+
+```go
+mock := clock.NewMock()
+count := 0
+
+// Kick off a timer to increment every 1 mock second.
+go func() {
+    ticker := clock.Ticker(1 * time.Second)
+    for {
+        <-ticker.C
+        count++
+    }
+}()
+runtime.Gosched()
+
+// Move the clock forward 10 seconds.
+mock.Add(10 * time.Second)
+
+// This prints 10.
+fmt.Println(count)
+```
+
+
diff --git a/vendor/github.com/benbjohnson/clock/clock.go b/vendor/github.com/benbjohnson/clock/clock.go
new file mode 100644
index 000000000..6a4edb2e8
--- /dev/null
+++ b/vendor/github.com/benbjohnson/clock/clock.go
@@ -0,0 +1,340 @@
+package clock
+
+import (
+	"sort"
+	"sync"
+	"time"
+)
+
+// Clock represents an interface to the functions in the standard library time
+// package. Two implementations are available in the clock package. The first
+// is a real-time clock which simply wraps the time package's functions. The
+// second is a mock clock which will only change when
+// programmatically adjusted.
+type Clock interface {
+	After(d time.Duration) <-chan time.Time
+	AfterFunc(d time.Duration, f func()) *Timer
+	Now() time.Time
+	Since(t time.Time) time.Duration
+	Sleep(d time.Duration)
+	Tick(d time.Duration) <-chan time.Time
+	Ticker(d time.Duration) *Ticker
+	Timer(d time.Duration) *Timer
+}
+
+// New returns an instance of a real-time clock.
+func New() Clock {
+	return &clock{}
+}
+
+// clock implements a real-time clock by simply wrapping the time package functions.
+type clock struct{}
+
+func (c *clock) After(d time.Duration) <-chan time.Time { return time.After(d) }
+
+func (c *clock) AfterFunc(d time.Duration, f func()) *Timer {
+	return &Timer{timer: time.AfterFunc(d, f)}
+}
+
+func (c *clock) Now() time.Time { return time.Now() }
+
+func (c *clock) Since(t time.Time) time.Duration { return time.Since(t) }
+
+func (c *clock) Sleep(d time.Duration) { time.Sleep(d) }
+
+func (c *clock) Tick(d time.Duration) <-chan time.Time { return time.Tick(d) }
+
+func (c *clock) Ticker(d time.Duration) *Ticker {
+	t := time.NewTicker(d)
+	return &Ticker{C: t.C, ticker: t}
+}
+
+func (c *clock) Timer(d time.Duration) *Timer {
+	t := time.NewTimer(d)
+	return &Timer{C: t.C, timer: t}
+}
+
+// Mock represents a mock clock that only moves forward programmatically.
+// It can be preferable to a real-time clock when testing time-based functionality.
+type Mock struct {
+	mu     sync.Mutex
+	now    time.Time   // current time
+	timers clockTimers // tickers & timers
+}
+
+// NewMock returns an instance of a mock clock.
+// The current time of the mock clock on initialization is the Unix epoch.
+func NewMock() *Mock {
+	return &Mock{now: time.Unix(0, 0)}
+}
+
+// Add moves the current time of the mock clock forward by the specified duration.
+// This should only be called from a single goroutine at a time.
+func (m *Mock) Add(d time.Duration) {
+	// Calculate the final current time.
+	t := m.now.Add(d)
+
+	// Continue to execute timers until there are no more before the new time.
+	for {
+		if !m.runNextTimer(t) {
+			break
+		}
+	}
+
+	// Ensure that we end with the new time.
+	m.mu.Lock()
+	m.now = t
+	m.mu.Unlock()
+
+	// Give a small buffer to make sure that other goroutines get handled.
+	gosched()
+}
+
+// Set sets the current time of the mock clock to a specific one.
+// This should only be called from a single goroutine at a time.
+func (m *Mock) Set(t time.Time) {
+	// Continue to execute timers until there are no more before the new time.
+	for {
+		if !m.runNextTimer(t) {
+			break
+		}
+	}
+
+	// Ensure that we end with the new time.
+	m.mu.Lock()
+	m.now = t
+	m.mu.Unlock()
+
+	// Give a small buffer to make sure that other goroutines get handled.
+	gosched()
+}
+
+// runNextTimer executes the next timer in chronological order and moves the
+// current time to the timer's next tick time. The next time is not executed if
+// its next time is after the max time. Returns true if a timer was executed.
+func (m *Mock) runNextTimer(max time.Time) bool {
+	m.mu.Lock()
+
+	// Sort timers by time.
+	sort.Sort(m.timers)
+
+	// If we have no more timers then exit.
+	if len(m.timers) == 0 {
+		m.mu.Unlock()
+		return false
+	}
+
+	// Retrieve next timer. Exit if next tick is after new time.
+	t := m.timers[0]
+	if t.Next().After(max) {
+		m.mu.Unlock()
+		return false
+	}
+
+	// Move "now" forward and unlock clock.
+	m.now = t.Next()
+	m.mu.Unlock()
+
+	// Execute timer.
+	t.Tick(m.now)
+	return true
+}
+
+// After waits for the duration to elapse and then sends the current time on the returned channel.
+func (m *Mock) After(d time.Duration) <-chan time.Time {
+	return m.Timer(d).C
+}
+
+// AfterFunc waits for the duration to elapse and then executes a function.
+// A Timer is returned that can be stopped.
+func (m *Mock) AfterFunc(d time.Duration, f func()) *Timer {
+	t := m.Timer(d)
+	t.C = nil
+	t.fn = f
+	return t
+}
+
+// Now returns the current wall time on the mock clock.
+func (m *Mock) Now() time.Time {
+	m.mu.Lock()
+	defer m.mu.Unlock()
+	return m.now
+}
+
+// Since returns time since the mock clock's wall time.
+func (m *Mock) Since(t time.Time) time.Duration {
+	return m.Now().Sub(t)
+}
+
+// Sleep pauses the goroutine for the given duration on the mock clock.
+// The clock must be moved forward in a separate goroutine.
+func (m *Mock) Sleep(d time.Duration) {
+	<-m.After(d)
+}
+
+// Tick is a convenience function for Ticker().
+// It will return a ticker channel that cannot be stopped.
+func (m *Mock) Tick(d time.Duration) <-chan time.Time {
+	return m.Ticker(d).C
+}
+
+// Ticker creates a new instance of Ticker.
+func (m *Mock) Ticker(d time.Duration) *Ticker {
+	m.mu.Lock()
+	defer m.mu.Unlock()
+	ch := make(chan time.Time, 1)
+	t := &Ticker{
+		C:    ch,
+		c:    ch,
+		mock: m,
+		d:    d,
+		next: m.now.Add(d),
+	}
+	m.timers = append(m.timers, (*internalTicker)(t))
+	return t
+}
+
+// Timer creates a new instance of Timer.
+func (m *Mock) Timer(d time.Duration) *Timer {
+	m.mu.Lock()
+	defer m.mu.Unlock()
+	ch := make(chan time.Time, 1)
+	t := &Timer{
+		C:       ch,
+		c:       ch,
+		mock:    m,
+		next:    m.now.Add(d),
+		stopped: false,
+	}
+	m.timers = append(m.timers, (*internalTimer)(t))
+	return t
+}
+
+func (m *Mock) removeClockTimer(t clockTimer) {
+	for i, timer := range m.timers {
+		if timer == t {
+			copy(m.timers[i:], m.timers[i+1:])
+			m.timers[len(m.timers)-1] = nil
+			m.timers = m.timers[:len(m.timers)-1]
+			break
+		}
+	}
+	sort.Sort(m.timers)
+}
+
+// clockTimer represents an object with an associated start time.
+type clockTimer interface {
+	Next() time.Time
+	Tick(time.Time)
+}
+
+// clockTimers represents a list of sortable timers.
+type clockTimers []clockTimer
+
+func (a clockTimers) Len() int           { return len(a) }
+func (a clockTimers) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
+func (a clockTimers) Less(i, j int) bool { return a[i].Next().Before(a[j].Next()) }
+
+// Timer represents a single event.
+// The current time will be sent on C, unless the timer was created by AfterFunc.
+type Timer struct {
+	C       <-chan time.Time
+	c       chan time.Time
+	timer   *time.Timer // realtime impl, if set
+	next    time.Time   // next tick time
+	mock    *Mock       // mock clock, if set
+	fn      func()      // AfterFunc function, if set
+	stopped bool        // True if stopped, false if running
+}
+
+// Stop turns off the ticker.
+func (t *Timer) Stop() bool {
+	if t.timer != nil {
+		return t.timer.Stop()
+	}
+
+	t.mock.mu.Lock()
+	registered := !t.stopped
+	t.mock.removeClockTimer((*internalTimer)(t))
+	t.stopped = true
+	t.mock.mu.Unlock()
+	return registered
+}
+
+// Reset changes the expiry time of the timer
+func (t *Timer) Reset(d time.Duration) bool {
+	if t.timer != nil {
+		return t.timer.Reset(d)
+	}
+
+	t.mock.mu.Lock()
+	t.next = t.mock.now.Add(d)
+	defer t.mock.mu.Unlock()
+
+	registered := !t.stopped
+	if t.stopped {
+		t.mock.timers = append(t.mock.timers, (*internalTimer)(t))
+	}
+
+	t.stopped = false
+	return registered
+}
+
+type internalTimer Timer
+
+func (t *internalTimer) Next() time.Time { return t.next }
+func (t *internalTimer) Tick(now time.Time) {
+	t.mock.mu.Lock()
+	if t.fn != nil {
+		t.fn()
+	} else {
+		t.c <- now
+	}
+	t.mock.removeClockTimer((*internalTimer)(t))
+	t.stopped = true
+	t.mock.mu.Unlock()
+	gosched()
+}
+
+// Ticker holds a channel that receives "ticks" at regular intervals.
+type Ticker struct {
+	C      <-chan time.Time
+	c      chan time.Time
+	ticker *time.Ticker  // realtime impl, if set
+	next   time.Time     // next tick time
+	mock   *Mock         // mock clock, if set
+	d      time.Duration // time between ticks
+}
+
+// Stop turns off the ticker.
+func (t *Ticker) Stop() {
+	if t.ticker != nil {
+		t.ticker.Stop()
+	} else {
+		t.mock.mu.Lock()
+		t.mock.removeClockTimer((*internalTicker)(t))
+		t.mock.mu.Unlock()
+	}
+}
+
+// Reset resets the ticker to a new duration.
+func (t *Ticker) Reset(dur time.Duration) {
+	if t.ticker != nil {
+		t.ticker.Reset(dur)
+	}
+}
+
+type internalTicker Ticker
+
+func (t *internalTicker) Next() time.Time { return t.next }
+func (t *internalTicker) Tick(now time.Time) {
+	select {
+	case t.c <- now:
+	default:
+	}
+	t.next = now.Add(t.d)
+	gosched()
+}
+
+// Sleep momentarily so that other goroutines can process.
+func gosched() { time.Sleep(1 * time.Millisecond) }
diff --git a/vendor/github.com/gorilla/websocket/README.md b/vendor/github.com/gorilla/websocket/README.md
index 19aa2e75c..2517a2871 100644
--- a/vendor/github.com/gorilla/websocket/README.md
+++ b/vendor/github.com/gorilla/websocket/README.md
@@ -6,6 +6,13 @@
 Gorilla WebSocket is a [Go](http://golang.org/) implementation of the
 [WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol.
 
+
+---
+
+⚠️ **[The Gorilla WebSocket Package is looking for a new maintainer](https://github.com/gorilla/websocket/issues/370)**
+
+---
+
 ### Documentation
 
 * [API Reference](https://pkg.go.dev/github.com/gorilla/websocket?tab=doc)
@@ -30,35 +37,3 @@ The Gorilla WebSocket package passes the server tests in the [Autobahn Test
 Suite](https://github.com/crossbario/autobahn-testsuite) using the application in the [examples/autobahn
 subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn).
 
-### Gorilla WebSocket compared with other packages
-
-<table>
-<tr>
-<th></th>
-<th><a href="http://godoc.org/github.com/gorilla/websocket">github.com/gorilla</a></th>
-<th><a href="http://godoc.org/golang.org/x/net/websocket">golang.org/x/net</a></th>
-</tr>
-<tr>
-<tr><td colspan="3"><a href="http://tools.ietf.org/html/rfc6455">RFC 6455</a> Features</td></tr>
-<tr><td>Passes <a href="https://github.com/crossbario/autobahn-testsuite">Autobahn Test Suite</a></td><td><a href="https://github.com/gorilla/websocket/tree/master/examples/autobahn">Yes</a></td><td>No</td></tr>
-<tr><td>Receive <a href="https://tools.ietf.org/html/rfc6455#section-5.4">fragmented</a> message<td>Yes</td><td><a href="https://code.google.com/p/go/issues/detail?id=7632">No</a>, see note 1</td></tr>
-<tr><td>Send <a href="https://tools.ietf.org/html/rfc6455#section-5.5.1">close</a> message</td><td><a href="http://godoc.org/github.com/gorilla/websocket#hdr-Control_Messages">Yes</a></td><td><a href="https://code.google.com/p/go/issues/detail?id=4588">No</a></td></tr>
-<tr><td>Send <a href="https://tools.ietf.org/html/rfc6455#section-5.5.2">pings</a> and receive <a href="https://tools.ietf.org/html/rfc6455#section-5.5.3">pongs</a></td><td><a href="http://godoc.org/github.com/gorilla/websocket#hdr-Control_Messages">Yes</a></td><td>No</td></tr>
-<tr><td>Get the <a href="https://tools.ietf.org/html/rfc6455#section-5.6">type</a> of a received data message</td><td>Yes</td><td>Yes, see note 2</td></tr>
-<tr><td colspan="3">Other Features</tr></td>
-<tr><td><a href="https://tools.ietf.org/html/rfc7692">Compression Extensions</a></td><td>Experimental</td><td>No</td></tr>
-<tr><td>Read message using io.Reader</td><td><a href="http://godoc.org/github.com/gorilla/websocket#Conn.NextReader">Yes</a></td><td>No, see note 3</td></tr>
-<tr><td>Write message using io.WriteCloser</td><td><a href="http://godoc.org/github.com/gorilla/websocket#Conn.NextWriter">Yes</a></td><td>No, see note 3</td></tr>
-</table>
-
-Notes:
-
-1. Large messages are fragmented in [Chrome's new WebSocket implementation](http://www.ietf.org/mail-archive/web/hybi/current/msg10503.html).
-2. The application can get the type of a received data message by implementing
-   a [Codec marshal](http://godoc.org/golang.org/x/net/websocket#Codec.Marshal)
-   function.
-3. The go.net io.Reader and io.Writer operate across WebSocket frame boundaries.
-  Read returns when the input buffer is full or a frame boundary is
-  encountered. Each call to Write sends a single frame message. The Gorilla
-  io.Reader and io.WriteCloser operate on a single WebSocket message.
-
diff --git a/vendor/github.com/gorilla/websocket/client.go b/vendor/github.com/gorilla/websocket/client.go
index 962c06a39..2efd83555 100644
--- a/vendor/github.com/gorilla/websocket/client.go
+++ b/vendor/github.com/gorilla/websocket/client.go
@@ -48,15 +48,23 @@ func NewClient(netConn net.Conn, u *url.URL, requestHeader http.Header, readBufS
 }
 
 // A Dialer contains options for connecting to WebSocket server.
+//
+// It is safe to call Dialer's methods concurrently.
 type Dialer struct {
 	// NetDial specifies the dial function for creating TCP connections. If
 	// NetDial is nil, net.Dial is used.
 	NetDial func(network, addr string) (net.Conn, error)
 
 	// NetDialContext specifies the dial function for creating TCP connections. If
-	// NetDialContext is nil, net.DialContext is used.
+	// NetDialContext is nil, NetDial is used.
 	NetDialContext func(ctx context.Context, network, addr string) (net.Conn, error)
 
+	// NetDialTLSContext specifies the dial function for creating TLS/TCP connections. If
+	// NetDialTLSContext is nil, NetDialContext is used.
+	// If NetDialTLSContext is set, Dial assumes the TLS handshake is done there and
+	// TLSClientConfig is ignored.
+	NetDialTLSContext func(ctx context.Context, network, addr string) (net.Conn, error)
+
 	// Proxy specifies a function to return a proxy for a given
 	// Request. If the function returns a non-nil error, the
 	// request is aborted with the provided error.
@@ -65,6 +73,8 @@ type Dialer struct {
 
 	// TLSClientConfig specifies the TLS configuration to use with tls.Client.
 	// If nil, the default configuration is used.
+	// If either NetDialTLS or NetDialTLSContext are set, Dial assumes the TLS handshake
+	// is done there and TLSClientConfig is ignored.
 	TLSClientConfig *tls.Config
 
 	// HandshakeTimeout specifies the duration for the handshake to complete.
@@ -176,7 +186,7 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
 	}
 
 	req := &http.Request{
-		Method:     "GET",
+		Method:     http.MethodGet,
 		URL:        u,
 		Proto:      "HTTP/1.1",
 		ProtoMajor: 1,
@@ -237,13 +247,32 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
 	// Get network dial function.
 	var netDial func(network, add string) (net.Conn, error)
 
-	if d.NetDialContext != nil {
-		netDial = func(network, addr string) (net.Conn, error) {
-			return d.NetDialContext(ctx, network, addr)
+	switch u.Scheme {
+	case "http":
+		if d.NetDialContext != nil {
+			netDial = func(network, addr string) (net.Conn, error) {
+				return d.NetDialContext(ctx, network, addr)
+			}
+		} else if d.NetDial != nil {
+			netDial = d.NetDial
 		}
-	} else if d.NetDial != nil {
-		netDial = d.NetDial
-	} else {
+	case "https":
+		if d.NetDialTLSContext != nil {
+			netDial = func(network, addr string) (net.Conn, error) {
+				return d.NetDialTLSContext(ctx, network, addr)
+			}
+		} else if d.NetDialContext != nil {
+			netDial = func(network, addr string) (net.Conn, error) {
+				return d.NetDialContext(ctx, network, addr)
+			}
+		} else if d.NetDial != nil {
+			netDial = d.NetDial
+		}
+	default:
+		return nil, nil, errMalformedURL
+	}
+
+	if netDial == nil {
 		netDialer := &net.Dialer{}
 		netDial = func(network, addr string) (net.Conn, error) {
 			return netDialer.DialContext(ctx, network, addr)
@@ -304,7 +333,9 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
 		}
 	}()
 
-	if u.Scheme == "https" {
+	if u.Scheme == "https" && d.NetDialTLSContext == nil {
+		// If NetDialTLSContext is set, assume that the TLS handshake has already been done
+
 		cfg := cloneTLSConfig(d.TLSClientConfig)
 		if cfg.ServerName == "" {
 			cfg.ServerName = hostNoPort
@@ -312,11 +343,12 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
 		tlsConn := tls.Client(netConn, cfg)
 		netConn = tlsConn
 
-		var err error
-		if trace != nil {
-			err = doHandshakeWithTrace(trace, tlsConn, cfg)
-		} else {
-			err = doHandshake(tlsConn, cfg)
+		if trace != nil && trace.TLSHandshakeStart != nil {
+			trace.TLSHandshakeStart()
+		}
+		err := doHandshake(ctx, tlsConn, cfg)
+		if trace != nil && trace.TLSHandshakeDone != nil {
+			trace.TLSHandshakeDone(tlsConn.ConnectionState(), err)
 		}
 
 		if err != nil {
@@ -348,8 +380,8 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
 	}
 
 	if resp.StatusCode != 101 ||
-		!strings.EqualFold(resp.Header.Get("Upgrade"), "websocket") ||
-		!strings.EqualFold(resp.Header.Get("Connection"), "upgrade") ||
+		!tokenListContainsValue(resp.Header, "Upgrade", "websocket") ||
+		!tokenListContainsValue(resp.Header, "Connection", "upgrade") ||
 		resp.Header.Get("Sec-Websocket-Accept") != computeAcceptKey(challengeKey) {
 		// Before closing the network connection on return from this
 		// function, slurp up some of the response to aid application
@@ -382,14 +414,9 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
 	return conn, resp, nil
 }
 
-func doHandshake(tlsConn *tls.Conn, cfg *tls.Config) error {
-	if err := tlsConn.Handshake(); err != nil {
-		return err
-	}
-	if !cfg.InsecureSkipVerify {
-		if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil {
-			return err
-		}
+func cloneTLSConfig(cfg *tls.Config) *tls.Config {
+	if cfg == nil {
+		return &tls.Config{}
 	}
-	return nil
+	return cfg.Clone()
 }
diff --git a/vendor/github.com/gorilla/websocket/client_clone.go b/vendor/github.com/gorilla/websocket/client_clone.go
deleted file mode 100644
index 4f0d94372..000000000
--- a/vendor/github.com/gorilla/websocket/client_clone.go
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build go1.8
-
-package websocket
-
-import "crypto/tls"
-
-func cloneTLSConfig(cfg *tls.Config) *tls.Config {
-	if cfg == nil {
-		return &tls.Config{}
-	}
-	return cfg.Clone()
-}
diff --git a/vendor/github.com/gorilla/websocket/client_clone_legacy.go b/vendor/github.com/gorilla/websocket/client_clone_legacy.go
deleted file mode 100644
index babb007fb..000000000
--- a/vendor/github.com/gorilla/websocket/client_clone_legacy.go
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2013 The Gorilla WebSocket Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !go1.8
-
-package websocket
-
-import "crypto/tls"
-
-// cloneTLSConfig clones all public fields except the fields
-// SessionTicketsDisabled and SessionTicketKey. This avoids copying the
-// sync.Mutex in the sync.Once and makes it safe to call cloneTLSConfig on a
-// config in active use.
-func cloneTLSConfig(cfg *tls.Config) *tls.Config {
-	if cfg == nil {
-		return &tls.Config{}
-	}
-	return &tls.Config{
-		Rand:                     cfg.Rand,
-		Time:                     cfg.Time,
-		Certificates:             cfg.Certificates,
-		NameToCertificate:        cfg.NameToCertificate,
-		GetCertificate:           cfg.GetCertificate,
-		RootCAs:                  cfg.RootCAs,
-		NextProtos:               cfg.NextProtos,
-		ServerName:               cfg.ServerName,
-		ClientAuth:               cfg.ClientAuth,
-		ClientCAs:                cfg.ClientCAs,
-		InsecureSkipVerify:       cfg.InsecureSkipVerify,
-		CipherSuites:             cfg.CipherSuites,
-		PreferServerCipherSuites: cfg.PreferServerCipherSuites,
-		ClientSessionCache:       cfg.ClientSessionCache,
-		MinVersion:               cfg.MinVersion,
-		MaxVersion:               cfg.MaxVersion,
-		CurvePreferences:         cfg.CurvePreferences,
-	}
-}
diff --git a/vendor/github.com/gorilla/websocket/conn.go b/vendor/github.com/gorilla/websocket/conn.go
index ca46d2f79..331eebc85 100644
--- a/vendor/github.com/gorilla/websocket/conn.go
+++ b/vendor/github.com/gorilla/websocket/conn.go
@@ -13,6 +13,7 @@ import (
 	"math/rand"
 	"net"
 	"strconv"
+	"strings"
 	"sync"
 	"time"
 	"unicode/utf8"
@@ -401,6 +402,12 @@ func (c *Conn) write(frameType int, deadline time.Time, buf0, buf1 []byte) error
 	return nil
 }
 
+func (c *Conn) writeBufs(bufs ...[]byte) error {
+	b := net.Buffers(bufs)
+	_, err := b.WriteTo(c.conn)
+	return err
+}
+
 // WriteControl writes a control message with the given deadline. The allowed
 // message types are CloseMessage, PingMessage and PongMessage.
 func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) error {
@@ -794,47 +801,69 @@ func (c *Conn) advanceFrame() (int, error) {
 	}
 
 	// 2. Read and parse first two bytes of frame header.
+	// To aid debugging, collect and report all errors in the first two bytes
+	// of the header.
+
+	var errors []string
 
 	p, err := c.read(2)
 	if err != nil {
 		return noFrame, err
 	}
 
-	final := p[0]&finalBit != 0
 	frameType := int(p[0] & 0xf)
+	final := p[0]&finalBit != 0
+	rsv1 := p[0]&rsv1Bit != 0
+	rsv2 := p[0]&rsv2Bit != 0
+	rsv3 := p[0]&rsv3Bit != 0
 	mask := p[1]&maskBit != 0
 	c.setReadRemaining(int64(p[1] & 0x7f))
 
 	c.readDecompress = false
-	if c.newDecompressionReader != nil && (p[0]&rsv1Bit) != 0 {
-		c.readDecompress = true
-		p[0] &^= rsv1Bit
+	if rsv1 {
+		if c.newDecompressionReader != nil {
+			c.readDecompress = true
+		} else {
+			errors = append(errors, "RSV1 set")
+		}
+	}
+
+	if rsv2 {
+		errors = append(errors, "RSV2 set")
 	}
 
-	if rsv := p[0] & (rsv1Bit | rsv2Bit | rsv3Bit); rsv != 0 {
-		return noFrame, c.handleProtocolError("unexpected reserved bits 0x" + strconv.FormatInt(int64(rsv), 16))
+	if rsv3 {
+		errors = append(errors, "RSV3 set")
 	}
 
 	switch frameType {
 	case CloseMessage, PingMessage, PongMessage:
 		if c.readRemaining > maxControlFramePayloadSize {
-			return noFrame, c.handleProtocolError("control frame length > 125")
+			errors = append(errors, "len > 125 for control")
 		}
 		if !final {
-			return noFrame, c.handleProtocolError("control frame not final")
+			errors = append(errors, "FIN not set on control")
 		}
 	case TextMessage, BinaryMessage:
 		if !c.readFinal {
-			return noFrame, c.handleProtocolError("message start before final message frame")
+			errors = append(errors, "data before FIN")
 		}
 		c.readFinal = final
 	case continuationFrame:
 		if c.readFinal {
-			return noFrame, c.handleProtocolError("continuation after final message frame")
+			errors = append(errors, "continuation after FIN")
 		}
 		c.readFinal = final
 	default:
-		return noFrame, c.handleProtocolError("unknown opcode " + strconv.Itoa(frameType))
+		errors = append(errors, "bad opcode "+strconv.Itoa(frameType))
+	}
+
+	if mask != c.isServer {
+		errors = append(errors, "bad MASK")
+	}
+
+	if len(errors) > 0 {
+		return noFrame, c.handleProtocolError(strings.Join(errors, ", "))
 	}
 
 	// 3. Read and parse frame length as per
@@ -872,10 +901,6 @@ func (c *Conn) advanceFrame() (int, error) {
 
 	// 4. Handle frame masking.
 
-	if mask != c.isServer {
-		return noFrame, c.handleProtocolError("incorrect mask flag")
-	}
-
 	if mask {
 		c.readMaskPos = 0
 		p, err := c.read(len(c.readMaskKey))
@@ -935,7 +960,7 @@ func (c *Conn) advanceFrame() (int, error) {
 		if len(payload) >= 2 {
 			closeCode = int(binary.BigEndian.Uint16(payload))
 			if !isValidReceivedCloseCode(closeCode) {
-				return noFrame, c.handleProtocolError("invalid close code")
+				return noFrame, c.handleProtocolError("bad close code " + strconv.Itoa(closeCode))
 			}
 			closeText = string(payload[2:])
 			if !utf8.ValidString(closeText) {
@@ -952,7 +977,11 @@ func (c *Conn) advanceFrame() (int, error) {
 }
 
 func (c *Conn) handleProtocolError(message string) error {
-	c.WriteControl(CloseMessage, FormatCloseMessage(CloseProtocolError, message), time.Now().Add(writeWait))
+	data := FormatCloseMessage(CloseProtocolError, message)
+	if len(data) > maxControlFramePayloadSize {
+		data = data[:maxControlFramePayloadSize]
+	}
+	c.WriteControl(CloseMessage, data, time.Now().Add(writeWait))
 	return errors.New("websocket: " + message)
 }
 
diff --git a/vendor/github.com/gorilla/websocket/conn_write.go b/vendor/github.com/gorilla/websocket/conn_write.go
deleted file mode 100644
index a509a21f8..000000000
--- a/vendor/github.com/gorilla/websocket/conn_write.go
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build go1.8
-
-package websocket
-
-import "net"
-
-func (c *Conn) writeBufs(bufs ...[]byte) error {
-	b := net.Buffers(bufs)
-	_, err := b.WriteTo(c.conn)
-	return err
-}
diff --git a/vendor/github.com/gorilla/websocket/conn_write_legacy.go b/vendor/github.com/gorilla/websocket/conn_write_legacy.go
deleted file mode 100644
index 37edaff5a..000000000
--- a/vendor/github.com/gorilla/websocket/conn_write_legacy.go
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2016 The Gorilla WebSocket Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-// +build !go1.8
-
-package websocket
-
-func (c *Conn) writeBufs(bufs ...[]byte) error {
-	for _, buf := range bufs {
-		if len(buf) > 0 {
-			if _, err := c.conn.Write(buf); err != nil {
-				return err
-			}
-		}
-	}
-	return nil
-}
diff --git a/vendor/github.com/gorilla/websocket/mask.go b/vendor/github.com/gorilla/websocket/mask.go
index 577fce9ef..d0742bf2a 100644
--- a/vendor/github.com/gorilla/websocket/mask.go
+++ b/vendor/github.com/gorilla/websocket/mask.go
@@ -2,6 +2,7 @@
 // this source code is governed by a BSD-style license that can be found in the
 // LICENSE file.
 
+//go:build !appengine
 // +build !appengine
 
 package websocket
diff --git a/vendor/github.com/gorilla/websocket/mask_safe.go b/vendor/github.com/gorilla/websocket/mask_safe.go
index 2aac060e5..36250ca7c 100644
--- a/vendor/github.com/gorilla/websocket/mask_safe.go
+++ b/vendor/github.com/gorilla/websocket/mask_safe.go
@@ -2,6 +2,7 @@
 // this source code is governed by a BSD-style license that can be found in the
 // LICENSE file.
 
+//go:build appengine
 // +build appengine
 
 package websocket
diff --git a/vendor/github.com/gorilla/websocket/proxy.go b/vendor/github.com/gorilla/websocket/proxy.go
index e87a8c9f0..e0f466b72 100644
--- a/vendor/github.com/gorilla/websocket/proxy.go
+++ b/vendor/github.com/gorilla/websocket/proxy.go
@@ -48,7 +48,7 @@ func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error)
 	}
 
 	connectReq := &http.Request{
-		Method: "CONNECT",
+		Method: http.MethodConnect,
 		URL:    &url.URL{Opaque: addr},
 		Host:   addr,
 		Header: connectHeader,
diff --git a/vendor/github.com/gorilla/websocket/server.go b/vendor/github.com/gorilla/websocket/server.go
index 887d55891..24d53b38a 100644
--- a/vendor/github.com/gorilla/websocket/server.go
+++ b/vendor/github.com/gorilla/websocket/server.go
@@ -23,6 +23,8 @@ func (e HandshakeError) Error() string { return e.message }
 
 // Upgrader specifies parameters for upgrading an HTTP connection to a
 // WebSocket connection.
+//
+// It is safe to call Upgrader's methods concurrently.
 type Upgrader struct {
 	// HandshakeTimeout specifies the duration for the handshake to complete.
 	HandshakeTimeout time.Duration
@@ -115,8 +117,8 @@ func (u *Upgrader) selectSubprotocol(r *http.Request, responseHeader http.Header
 // Upgrade upgrades the HTTP server connection to the WebSocket protocol.
 //
 // The responseHeader is included in the response to the client's upgrade
-// request. Use the responseHeader to specify cookies (Set-Cookie) and the
-// application negotiated subprotocol (Sec-WebSocket-Protocol).
+// request. Use the responseHeader to specify cookies (Set-Cookie). To specify
+// subprotocols supported by the server, set Upgrader.Subprotocols directly.
 //
 // If the upgrade fails, then Upgrade replies to the client with an HTTP error
 // response.
@@ -131,7 +133,7 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
 		return u.returnError(w, r, http.StatusBadRequest, badHandshake+"'websocket' token not found in 'Upgrade' header")
 	}
 
-	if r.Method != "GET" {
+	if r.Method != http.MethodGet {
 		return u.returnError(w, r, http.StatusMethodNotAllowed, badHandshake+"request method is not GET")
 	}
 
diff --git a/vendor/github.com/gorilla/websocket/tls_handshake.go b/vendor/github.com/gorilla/websocket/tls_handshake.go
new file mode 100644
index 000000000..a62b68ccb
--- /dev/null
+++ b/vendor/github.com/gorilla/websocket/tls_handshake.go
@@ -0,0 +1,21 @@
+//go:build go1.17
+// +build go1.17
+
+package websocket
+
+import (
+	"context"
+	"crypto/tls"
+)
+
+func doHandshake(ctx context.Context, tlsConn *tls.Conn, cfg *tls.Config) error {
+	if err := tlsConn.HandshakeContext(ctx); err != nil {
+		return err
+	}
+	if !cfg.InsecureSkipVerify {
+		if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil {
+			return err
+		}
+	}
+	return nil
+}
diff --git a/vendor/github.com/gorilla/websocket/tls_handshake_116.go b/vendor/github.com/gorilla/websocket/tls_handshake_116.go
new file mode 100644
index 000000000..e1b2b44f6
--- /dev/null
+++ b/vendor/github.com/gorilla/websocket/tls_handshake_116.go
@@ -0,0 +1,21 @@
+//go:build !go1.17
+// +build !go1.17
+
+package websocket
+
+import (
+	"context"
+	"crypto/tls"
+)
+
+func doHandshake(ctx context.Context, tlsConn *tls.Conn, cfg *tls.Config) error {
+	if err := tlsConn.Handshake(); err != nil {
+		return err
+	}
+	if !cfg.InsecureSkipVerify {
+		if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil {
+			return err
+		}
+	}
+	return nil
+}
diff --git a/vendor/github.com/gorilla/websocket/trace.go b/vendor/github.com/gorilla/websocket/trace.go
deleted file mode 100644
index 834f122a0..000000000
--- a/vendor/github.com/gorilla/websocket/trace.go
+++ /dev/null
@@ -1,19 +0,0 @@
-// +build go1.8
-
-package websocket
-
-import (
-	"crypto/tls"
-	"net/http/httptrace"
-)
-
-func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error {
-	if trace.TLSHandshakeStart != nil {
-		trace.TLSHandshakeStart()
-	}
-	err := doHandshake(tlsConn, cfg)
-	if trace.TLSHandshakeDone != nil {
-		trace.TLSHandshakeDone(tlsConn.ConnectionState(), err)
-	}
-	return err
-}
diff --git a/vendor/github.com/gorilla/websocket/trace_17.go b/vendor/github.com/gorilla/websocket/trace_17.go
deleted file mode 100644
index 77d05a0b5..000000000
--- a/vendor/github.com/gorilla/websocket/trace_17.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// +build !go1.8
-
-package websocket
-
-import (
-	"crypto/tls"
-	"net/http/httptrace"
-)
-
-func doHandshakeWithTrace(trace *httptrace.ClientTrace, tlsConn *tls.Conn, cfg *tls.Config) error {
-	return doHandshake(tlsConn, cfg)
-}
diff --git a/vendor/go.uber.org/zap/.readme.tmpl b/vendor/go.uber.org/zap/.readme.tmpl
index 3154a1e64..92aa65d66 100644
--- a/vendor/go.uber.org/zap/.readme.tmpl
+++ b/vendor/go.uber.org/zap/.readme.tmpl
@@ -96,14 +96,14 @@ Released under the [MIT License](LICENSE.txt).
 
 <sup id="footnote-versions">1</sup> In particular, keep in mind that we may be
 benchmarking against slightly older versions of other packages. Versions are
-pinned in zap's [glide.lock][] file. [↩](#anchor-versions)
+pinned in the [benchmarks/go.mod][] file. [↩](#anchor-versions)
 
-[doc-img]: https://godoc.org/go.uber.org/zap?status.svg
-[doc]: https://godoc.org/go.uber.org/zap
-[ci-img]: https://travis-ci.com/uber-go/zap.svg?branch=master
-[ci]: https://travis-ci.com/uber-go/zap
+[doc-img]: https://pkg.go.dev/badge/go.uber.org/zap
+[doc]: https://pkg.go.dev/go.uber.org/zap
+[ci-img]: https://github.com/uber-go/zap/actions/workflows/go.yml/badge.svg
+[ci]: https://github.com/uber-go/zap/actions/workflows/go.yml
 [cov-img]: https://codecov.io/gh/uber-go/zap/branch/master/graph/badge.svg
 [cov]: https://codecov.io/gh/uber-go/zap
 [benchmarking suite]: https://github.com/uber-go/zap/tree/master/benchmarks
-[glide.lock]: https://github.com/uber-go/zap/blob/master/glide.lock
+[benchmarks/go.mod]: https://github.com/uber-go/zap/blob/master/benchmarks/go.mod
 
diff --git a/vendor/go.uber.org/zap/CHANGELOG.md b/vendor/go.uber.org/zap/CHANGELOG.md
index 794ee303e..0db1f9f15 100644
--- a/vendor/go.uber.org/zap/CHANGELOG.md
+++ b/vendor/go.uber.org/zap/CHANGELOG.md
@@ -3,9 +3,110 @@ 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).
 
+## 1.24.0 (30 Nov 2022)
+
+Enhancements:
+* [#1148][]: Add `Level` to both `Logger` and `SugaredLogger` that reports the
+  current minimum enabled log level.
+* [#1185][]: `SugaredLogger` turns errors to zap.Error automatically.
+
+Thanks to @Abirdcfly, @craigpastro, @nnnkkk7, and @sashamelentyev for their
+contributions to this release.
+
+[#1148]: https://github.coml/uber-go/zap/pull/1148
+[#1185]: https://github.coml/uber-go/zap/pull/1185
+
+## 1.23.0 (24 Aug 2022)
+
+Enhancements:
+* [#1147][]: Add a `zapcore.LevelOf` function to determine the level of a
+  `LevelEnabler` or `Core`.
+* [#1155][]: Add `zap.Stringers` field constructor to log arrays of objects
+  that implement `String() string`.
+
+[#1147]: https://github.com/uber-go/zap/pull/1147
+[#1155]: https://github.com/uber-go/zap/pull/1155
+
+
+## 1.22.0 (8 Aug 2022)
+
+Enhancements:
+* [#1071][]: Add `zap.Objects` and `zap.ObjectValues` field constructors to log
+  arrays of objects. With these two constructors, you don't need to implement
+  `zapcore.ArrayMarshaler` for use with `zap.Array` if those objects implement
+  `zapcore.ObjectMarshaler`.
+* [#1079][]: Add `SugaredLogger.WithOptions` to build a copy of an existing
+  `SugaredLogger` with the provided options applied.
+* [#1080][]: Add `*ln` variants to `SugaredLogger` for each log level.
+  These functions provide a string joining behavior similar to `fmt.Println`.
+* [#1088][]: Add `zap.WithFatalHook` option to control the behavior of the
+  logger for `Fatal`-level log entries. This defaults to exiting the program.
+* [#1108][]: Add a `zap.Must` function that you can use with `NewProduction` or
+  `NewDevelopment` to panic if the system was unable to build the logger.
+* [#1118][]: Add a `Logger.Log` method that allows specifying the log level for
+  a statement dynamically.
+
+Thanks to @cardil, @craigpastro, @sashamelentyev, @shota3506, and @zhupeijun
+for their contributions to this release.
+
+[#1071]: https://github.com/uber-go/zap/pull/1071
+[#1079]: https://github.com/uber-go/zap/pull/1079
+[#1080]: https://github.com/uber-go/zap/pull/1080
+[#1088]: https://github.com/uber-go/zap/pull/1088
+[#1108]: https://github.com/uber-go/zap/pull/1108
+[#1118]: https://github.com/uber-go/zap/pull/1118
+
+## 1.21.0 (7 Feb 2022)
+
+Enhancements:
+*  [#1047][]: Add `zapcore.ParseLevel` to parse a `Level` from a string.
+*  [#1048][]: Add `zap.ParseAtomicLevel` to parse an `AtomicLevel` from a
+   string.
+
+Bugfixes:
+* [#1058][]: Fix panic in JSON encoder when `EncodeLevel` is unset.
+
+Other changes:
+* [#1052][]: Improve encoding performance when the `AddCaller` and
+  `AddStacktrace` options are used together.
+
+[#1047]: https://github.com/uber-go/zap/pull/1047
+[#1048]: https://github.com/uber-go/zap/pull/1048
+[#1052]: https://github.com/uber-go/zap/pull/1052
+[#1058]: https://github.com/uber-go/zap/pull/1058
+
+Thanks to @aerosol and @Techassi for their contributions to this release.
+
+## 1.20.0 (4 Jan 2022)
+
+Enhancements:
+* [#989][]: Add `EncoderConfig.SkipLineEnding` flag to disable adding newline
+  characters between log statements.
+* [#1039][]: Add `EncoderConfig.NewReflectedEncoder` field to customize JSON
+  encoding of reflected log fields.
+
+Bugfixes:
+* [#1011][]: Fix inaccurate precision when encoding complex64 as JSON.
+* [#554][], [#1017][]: Close JSON namespaces opened in `MarshalLogObject`
+  methods when the methods return.
+* [#1033][]: Avoid panicking in Sampler core if `thereafter` is zero.
+
+Other changes:
+* [#1028][]: Drop support for Go < 1.15.
+
+[#554]: https://github.com/uber-go/zap/pull/554
+[#989]: https://github.com/uber-go/zap/pull/989
+[#1011]: https://github.com/uber-go/zap/pull/1011
+[#1017]: https://github.com/uber-go/zap/pull/1017
+[#1028]: https://github.com/uber-go/zap/pull/1028
+[#1033]: https://github.com/uber-go/zap/pull/1033
+[#1039]: https://github.com/uber-go/zap/pull/1039
+
+Thanks to @psrajat, @lruggieri, @sammyrnycreal for their contributions to this release.
+
 ## 1.19.1 (8 Sep 2021)
 
-### Fixed
+Bugfixes:
 * [#1001][]: JSON: Fix complex number encoding with negative imaginary part. Thanks to @hemantjadon.
 * [#1003][]: JSON: Fix inaccurate precision when encoding float32.
 
diff --git a/vendor/go.uber.org/zap/CONTRIBUTING.md b/vendor/go.uber.org/zap/CONTRIBUTING.md
index 5cd965687..ea02f3cae 100644
--- a/vendor/go.uber.org/zap/CONTRIBUTING.md
+++ b/vendor/go.uber.org/zap/CONTRIBUTING.md
@@ -16,7 +16,7 @@ you to accept the CLA when you open your pull request.
 
 [Fork][fork], then clone the repository:
 
-```
+```bash
 mkdir -p $GOPATH/src/go.uber.org
 cd $GOPATH/src/go.uber.org
 git clone git@github.com:your_github_username/zap.git
@@ -27,21 +27,16 @@ git fetch upstream
 
 Make sure that the tests and the linters pass:
 
-```
+```bash
 make test
 make lint
 ```
 
-If you're not using the minor version of Go specified in the Makefile's
-`LINTABLE_MINOR_VERSIONS` variable, `make lint` doesn't do anything. This is
-fine, but it means that you'll only discover lint failures after you open your
-pull request.
-
 ## Making Changes
 
 Start by creating a new branch for your changes:
 
-```
+```bash
 cd $GOPATH/src/go.uber.org/zap
 git checkout master
 git fetch upstream
@@ -52,22 +47,22 @@ git checkout -b cool_new_feature
 Make your changes, then ensure that `make lint` and `make test` still pass. If
 you're satisfied with your changes, push them to your fork.
 
-```
+```bash
 git push origin cool_new_feature
 ```
 
 Then use the GitHub UI to open a pull request.
 
-At this point, you're waiting on us to review your changes. We *try* to respond
+At this point, you're waiting on us to review your changes. We _try_ to respond
 to issues and pull requests within a few business days, and we may suggest some
 improvements or alternatives. Once your changes are approved, one of the
 project maintainers will merge them.
 
 We're much more likely to approve your changes if you:
 
-* Add tests for new functionality.
-* Write a [good commit message][commit-message].
-* Maintain backward compatibility.
+- Add tests for new functionality.
+- Write a [good commit message][commit-message].
+- Maintain backward compatibility.
 
 [fork]: https://github.com/uber-go/zap/fork
 [open-issue]: https://github.com/uber-go/zap/issues/new
diff --git a/vendor/go.uber.org/zap/README.md b/vendor/go.uber.org/zap/README.md
index 1e64d6cff..a553a428c 100644
--- a/vendor/go.uber.org/zap/README.md
+++ b/vendor/go.uber.org/zap/README.md
@@ -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
 JSON encoder, and the base `Logger` strives to avoid serialization overhead
 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.
 
 As measured by its own [benchmarking suite][], not only is zap more performant
@@ -64,40 +64,40 @@ id="anchor-versions">[1](#footnote-versions)</sup>
 
 Log a message and 10 fields:
 
-| Package | Time | Time % to zap | Objects Allocated |
-| :------ | :--: | :-----------: | :---------------: |
-| :zap: zap | 862 ns/op | +0% | 5 allocs/op
-| :zap: zap (sugared) | 1250 ns/op | +45% | 11 allocs/op
-| zerolog | 4021 ns/op | +366% | 76 allocs/op
-| go-kit | 4542 ns/op | +427% | 105 allocs/op
-| apex/log | 26785 ns/op | +3007% | 115 allocs/op
-| logrus | 29501 ns/op | +3322% | 125 allocs/op
-| log15 | 29906 ns/op | +3369% | 122 allocs/op
+| Package             |    Time     | Time % to zap | Objects Allocated |
+| :------------------ | :---------: | :-----------: | :---------------: |
+| :zap: zap           | 2900 ns/op  |      +0%      |    5 allocs/op    |
+| :zap: zap (sugared) | 3475 ns/op  |     +20%      |   10 allocs/op    |
+| zerolog             | 10639 ns/op |     +267%     |   32 allocs/op    |
+| go-kit              | 14434 ns/op |     +398%     |   59 allocs/op    |
+| logrus              | 17104 ns/op |     +490%     |   81 allocs/op    |
+| apex/log            | 32424 ns/op |    +1018%     |   66 allocs/op    |
+| log15               | 33579 ns/op |    +1058%     |   76 allocs/op    |
 
 Log a message with a logger that already has 10 fields of context:
 
-| Package | Time | Time % to zap | Objects Allocated |
-| :------ | :--: | :-----------: | :---------------: |
-| :zap: zap | 126 ns/op | +0% | 0 allocs/op
-| :zap: zap (sugared) | 187 ns/op | +48% | 2 allocs/op
-| zerolog | 88 ns/op | -30% | 0 allocs/op
-| go-kit | 5087 ns/op | +3937% | 103 allocs/op
-| log15 | 18548 ns/op | +14621% | 73 allocs/op
-| apex/log | 26012 ns/op | +20544% | 104 allocs/op
-| logrus | 27236 ns/op | +21516% | 113 allocs/op
+| Package             |    Time     | Time % to zap | Objects Allocated |
+| :------------------ | :---------: | :-----------: | :---------------: |
+| :zap: zap           |  373 ns/op  |      +0%      |    0 allocs/op    |
+| :zap: zap (sugared) |  452 ns/op  |     +21%      |    1 allocs/op    |
+| zerolog             |  288 ns/op  |     -23%      |    0 allocs/op    |
+| go-kit              | 11785 ns/op |    +3060%     |   58 allocs/op    |
+| logrus              | 19629 ns/op |    +5162%     |   70 allocs/op    |
+| log15               | 21866 ns/op |    +5762%     |   72 allocs/op    |
+| apex/log            | 30890 ns/op |    +8182%     |   55 allocs/op    |
 
 Log a static string, without any context or `printf`-style templating:
 
-| Package | Time | Time % to zap | Objects Allocated |
-| :------ | :--: | :-----------: | :---------------: |
-| :zap: zap | 118 ns/op | +0% | 0 allocs/op
-| :zap: zap (sugared) | 191 ns/op | +62% | 2 allocs/op
-| zerolog | 93 ns/op | -21% | 0 allocs/op
-| go-kit | 280 ns/op | +137% | 11 allocs/op
-| standard library | 499 ns/op | +323% | 2 allocs/op
-| apex/log | 1990 ns/op | +1586% | 10 allocs/op
-| logrus | 3129 ns/op | +2552% | 24 allocs/op
-| log15 | 3887 ns/op | +3194% | 23 allocs/op
+| Package             |    Time    | Time % to zap | Objects Allocated |
+| :------------------ | :--------: | :-----------: | :---------------: |
+| :zap: zap           | 381 ns/op  |      +0%      |    0 allocs/op    |
+| :zap: zap (sugared) | 410 ns/op  |      +8%      |    1 allocs/op    |
+| zerolog             | 369 ns/op  |      -3%      |    0 allocs/op    |
+| standard library    | 385 ns/op  |      +1%      |    2 allocs/op    |
+| go-kit              | 606 ns/op  |     +59%      |   11 allocs/op    |
+| logrus              | 1730 ns/op |     +354%     |   25 allocs/op    |
+| apex/log            | 1998 ns/op |     +424%     |    7 allocs/op    |
+| log15               | 4546 ns/op |    +1093%     |   22 allocs/op    |
 
 ## Development Status: Stable
 
@@ -131,4 +131,3 @@ pinned in the [benchmarks/go.mod][] file. [↩](#anchor-versions)
 [cov]: https://codecov.io/gh/uber-go/zap
 [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
-
diff --git a/vendor/go.uber.org/zap/array_go118.go b/vendor/go.uber.org/zap/array_go118.go
new file mode 100644
index 000000000..d0d2c49d6
--- /dev/null
+++ b/vendor/go.uber.org/zap/array_go118.go
@@ -0,0 +1,156 @@
+// Copyright (c) 2022 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.18
+// +build go1.18
+
+package zap
+
+import (
+	"fmt"
+
+	"go.uber.org/zap/zapcore"
+)
+
+// Objects constructs a field with the given key, holding a list of the
+// provided objects that can be marshaled by Zap.
+//
+// Note that these objects must implement zapcore.ObjectMarshaler directly.
+// That is, if you're trying to marshal a []Request, the MarshalLogObject
+// method must be declared on the Request type, not its pointer (*Request).
+// If it's on the pointer, use ObjectValues.
+//
+// Given an object that implements MarshalLogObject on the value receiver, you
+// can log a slice of those objects with Objects like so:
+//
+//	type Author struct{ ... }
+//	func (a Author) MarshalLogObject(enc zapcore.ObjectEncoder) error
+//
+//	var authors []Author = ...
+//	logger.Info("loading article", zap.Objects("authors", authors))
+//
+// Similarly, given a type that implements MarshalLogObject on its pointer
+// receiver, you can log a slice of pointers to that object with Objects like
+// so:
+//
+//	type Request struct{ ... }
+//	func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error
+//
+//	var requests []*Request = ...
+//	logger.Info("sending requests", zap.Objects("requests", requests))
+//
+// If instead, you have a slice of values of such an object, use the
+// ObjectValues constructor.
+//
+//	var requests []Request = ...
+//	logger.Info("sending requests", zap.ObjectValues("requests", requests))
+func Objects[T zapcore.ObjectMarshaler](key string, values []T) Field {
+	return Array(key, objects[T](values))
+}
+
+type objects[T zapcore.ObjectMarshaler] []T
+
+func (os objects[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error {
+	for _, o := range os {
+		if err := arr.AppendObject(o); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// ObjectMarshalerPtr is a constraint that specifies that the given type
+// implements zapcore.ObjectMarshaler on a pointer receiver.
+type ObjectMarshalerPtr[T any] interface {
+	*T
+	zapcore.ObjectMarshaler
+}
+
+// ObjectValues constructs a field with the given key, holding a list of the
+// provided objects, where pointers to these objects can be marshaled by Zap.
+//
+// Note that pointers to these objects must implement zapcore.ObjectMarshaler.
+// That is, if you're trying to marshal a []Request, the MarshalLogObject
+// method must be declared on the *Request type, not the value (Request).
+// If it's on the value, use Objects.
+//
+// Given an object that implements MarshalLogObject on the pointer receiver,
+// you can log a slice of those objects with ObjectValues like so:
+//
+//	type Request struct{ ... }
+//	func (r *Request) MarshalLogObject(enc zapcore.ObjectEncoder) error
+//
+//	var requests []Request = ...
+//	logger.Info("sending requests", zap.ObjectValues("requests", requests))
+//
+// If instead, you have a slice of pointers of such an object, use the Objects
+// field constructor.
+//
+//	var requests []*Request = ...
+//	logger.Info("sending requests", zap.Objects("requests", requests))
+func ObjectValues[T any, P ObjectMarshalerPtr[T]](key string, values []T) Field {
+	return Array(key, objectValues[T, P](values))
+}
+
+type objectValues[T any, P ObjectMarshalerPtr[T]] []T
+
+func (os objectValues[T, P]) MarshalLogArray(arr zapcore.ArrayEncoder) error {
+	for i := range os {
+		// It is necessary for us to explicitly reference the "P" type.
+		// We cannot simply pass "&os[i]" to AppendObject because its type
+		// is "*T", which the type system does not consider as
+		// implementing ObjectMarshaler.
+		// Only the type "P" satisfies ObjectMarshaler, which we have
+		// to convert "*T" to explicitly.
+		var p P = &os[i]
+		if err := arr.AppendObject(p); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+// Stringers constructs a field with the given key, holding a list of the
+// output provided by the value's String method
+//
+// Given an object that implements String on the value receiver, you
+// can log a slice of those objects with Objects like so:
+//
+//	type Request struct{ ... }
+//	func (a Request) String() string
+//
+//	var requests []Request = ...
+//	logger.Info("sending requests", zap.Stringers("requests", requests))
+//
+// Note that these objects must implement fmt.Stringer directly.
+// That is, if you're trying to marshal a []Request, the String method
+// must be declared on the Request type, not its pointer (*Request).
+func Stringers[T fmt.Stringer](key string, values []T) Field {
+	return Array(key, stringers[T](values))
+}
+
+type stringers[T fmt.Stringer] []T
+
+func (os stringers[T]) MarshalLogArray(arr zapcore.ArrayEncoder) error {
+	for _, o := range os {
+		arr.AppendString(o.String())
+	}
+	return nil
+}
diff --git a/vendor/go.uber.org/zap/config.go b/vendor/go.uber.org/zap/config.go
index 55637fb0b..ee6096766 100644
--- a/vendor/go.uber.org/zap/config.go
+++ b/vendor/go.uber.org/zap/config.go
@@ -21,7 +21,7 @@
 package zap
 
 import (
-	"fmt"
+	"errors"
 	"sort"
 	"time"
 
@@ -182,7 +182,7 @@ func (cfg Config) Build(opts ...Option) (*Logger, error) {
 	}
 
 	if cfg.Level == (AtomicLevel{}) {
-		return nil, fmt.Errorf("missing Level")
+		return nil, errors.New("missing Level")
 	}
 
 	log := New(
diff --git a/vendor/go.uber.org/zap/doc.go b/vendor/go.uber.org/zap/doc.go
index 8638dd1b9..3c50d7b4d 100644
--- a/vendor/go.uber.org/zap/doc.go
+++ b/vendor/go.uber.org/zap/doc.go
@@ -32,7 +32,7 @@
 // they need to count every allocation and when they'd prefer a more familiar,
 // loosely typed API.
 //
-// Choosing a Logger
+// # Choosing a Logger
 //
 // In contexts where performance is nice, but not critical, use the
 // SugaredLogger. It's 4-10x faster than other structured logging packages and
@@ -41,14 +41,15 @@
 // variadic number of key-value pairs. (For more advanced use cases, they also
 // accept strongly typed fields - see the SugaredLogger.With documentation for
 // details.)
-//  sugar := zap.NewExample().Sugar()
-//  defer sugar.Sync()
-//  sugar.Infow("failed to fetch URL",
-//    "url", "http://example.com",
-//    "attempt", 3,
-//    "backoff", time.Second,
-//  )
-//  sugar.Infof("failed to fetch URL: %s", "http://example.com")
+//
+//	sugar := zap.NewExample().Sugar()
+//	defer sugar.Sync()
+//	sugar.Infow("failed to fetch URL",
+//	  "url", "http://example.com",
+//	  "attempt", 3,
+//	  "backoff", time.Second,
+//	)
+//	sugar.Infof("failed to fetch URL: %s", "http://example.com")
 //
 // By default, loggers are unbuffered. However, since zap's low-level APIs
 // allow buffering, calling Sync before letting your process exit is a good
@@ -57,32 +58,35 @@
 // In the rare contexts where every microsecond and every allocation matter,
 // use the Logger. It's even faster than the SugaredLogger and allocates far
 // less, but it only supports strongly-typed, structured logging.
-//  logger := zap.NewExample()
-//  defer logger.Sync()
-//  logger.Info("failed to fetch URL",
-//    zap.String("url", "http://example.com"),
-//    zap.Int("attempt", 3),
-//    zap.Duration("backoff", time.Second),
-//  )
+//
+//	logger := zap.NewExample()
+//	defer logger.Sync()
+//	logger.Info("failed to fetch URL",
+//	  zap.String("url", "http://example.com"),
+//	  zap.Int("attempt", 3),
+//	  zap.Duration("backoff", time.Second),
+//	)
 //
 // Choosing between the Logger and SugaredLogger doesn't need to be an
 // application-wide decision: converting between the two is simple and
 // inexpensive.
-//   logger := zap.NewExample()
-//   defer logger.Sync()
-//   sugar := logger.Sugar()
-//   plain := sugar.Desugar()
 //
-// Configuring Zap
+//	logger := zap.NewExample()
+//	defer logger.Sync()
+//	sugar := logger.Sugar()
+//	plain := sugar.Desugar()
+//
+// # Configuring Zap
 //
 // The simplest way to build a Logger is to use zap's opinionated presets:
 // NewExample, NewProduction, and NewDevelopment. These presets build a logger
 // with a single function call:
-//  logger, err := zap.NewProduction()
-//  if err != nil {
-//    log.Fatalf("can't initialize zap logger: %v", err)
-//  }
-//  defer logger.Sync()
+//
+//	logger, err := zap.NewProduction()
+//	if err != nil {
+//	  log.Fatalf("can't initialize zap logger: %v", err)
+//	}
+//	defer logger.Sync()
 //
 // Presets are fine for small projects, but larger projects and organizations
 // naturally require a bit more customization. For most users, zap's Config
@@ -94,7 +98,7 @@
 // go.uber.org/zap/zapcore. See the package-level AdvancedConfiguration
 // example for sample code.
 //
-// Extending Zap
+// # Extending Zap
 //
 // The zap package itself is a relatively thin wrapper around the interfaces
 // in go.uber.org/zap/zapcore. Extending zap to support a new encoding (e.g.,
@@ -106,7 +110,7 @@
 // Similarly, package authors can use the high-performance Encoder and Core
 // implementations in the zapcore package to build their own loggers.
 //
-// Frequently Asked Questions
+// # Frequently Asked Questions
 //
 // An FAQ covering everything from installation errors to design decisions is
 // available at https://github.com/uber-go/zap/blob/master/FAQ.md.
diff --git a/vendor/go.uber.org/zap/encoder.go b/vendor/go.uber.org/zap/encoder.go
index 08ed83354..caa04ceef 100644
--- a/vendor/go.uber.org/zap/encoder.go
+++ b/vendor/go.uber.org/zap/encoder.go
@@ -63,7 +63,7 @@ func RegisterEncoder(name string, constructor func(zapcore.EncoderConfig) (zapco
 
 func newEncoder(name string, encoderConfig zapcore.EncoderConfig) (zapcore.Encoder, error) {
 	if encoderConfig.TimeKey != "" && encoderConfig.EncodeTime == nil {
-		return nil, fmt.Errorf("missing EncodeTime in EncoderConfig")
+		return nil, errors.New("missing EncodeTime in EncoderConfig")
 	}
 
 	_encoderMutex.RLock()
diff --git a/vendor/go.uber.org/zap/global.go b/vendor/go.uber.org/zap/global.go
index c1ac0507c..3cb46c9e0 100644
--- a/vendor/go.uber.org/zap/global.go
+++ b/vendor/go.uber.org/zap/global.go
@@ -31,6 +31,7 @@ import (
 )
 
 const (
+	_stdLogDefaultDepth      = 1
 	_loggerWriterDepth       = 2
 	_programmerErrorTemplate = "You've found a bug in zap! Please file a bug at " +
 		"https://github.com/uber-go/zap/issues/new and reference this error: %v"
diff --git a/vendor/go.uber.org/zap/http_handler.go b/vendor/go.uber.org/zap/http_handler.go
index 1297c33b3..632b6831a 100644
--- a/vendor/go.uber.org/zap/http_handler.go
+++ b/vendor/go.uber.org/zap/http_handler.go
@@ -22,6 +22,7 @@ package zap
 
 import (
 	"encoding/json"
+	"errors"
 	"fmt"
 	"io"
 	"net/http"
@@ -32,22 +33,23 @@ import (
 // ServeHTTP is a simple JSON endpoint that can report on or change the current
 // logging level.
 //
-// GET
+// # GET
 //
 // The GET request returns a JSON description of the current logging level like:
-//   {"level":"info"}
 //
-// PUT
+//	{"level":"info"}
+//
+// # PUT
 //
 // The PUT request changes the logging level. It is perfectly safe to change the
 // logging level while a program is running. Two content types are supported:
 //
-//    Content-Type: application/x-www-form-urlencoded
+//	Content-Type: application/x-www-form-urlencoded
 //
 // With this content type, the level can be provided through the request body or
 // a query parameter. The log level is URL encoded like:
 //
-//    level=debug
+//	level=debug
 //
 // The request body takes precedence over the query parameter, if both are
 // specified.
@@ -55,18 +57,17 @@ import (
 // This content type is the default for a curl PUT request. Following are two
 // example curl requests that both set the logging level to debug.
 //
-//    curl -X PUT localhost:8080/log/level?level=debug
-//    curl -X PUT localhost:8080/log/level -d level=debug
+//	curl -X PUT localhost:8080/log/level?level=debug
+//	curl -X PUT localhost:8080/log/level -d level=debug
 //
 // For any other content type, the payload is expected to be JSON encoded and
 // look like:
 //
-//   {"level":"info"}
+//	{"level":"info"}
 //
 // An example curl request could look like this:
 //
-//    curl -X PUT localhost:8080/log/level -H "Content-Type: application/json" -d '{"level":"debug"}'
-//
+//	curl -X PUT localhost:8080/log/level -H "Content-Type: application/json" -d '{"level":"debug"}'
 func (lvl AtomicLevel) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 	type errorResponse struct {
 		Error string `json:"error"`
@@ -108,7 +109,7 @@ func decodePutRequest(contentType string, r *http.Request) (zapcore.Level, error
 func decodePutURL(r *http.Request) (zapcore.Level, error) {
 	lvl := r.FormValue("level")
 	if lvl == "" {
-		return 0, fmt.Errorf("must specify logging level")
+		return 0, errors.New("must specify logging level")
 	}
 	var l zapcore.Level
 	if err := l.UnmarshalText([]byte(lvl)); err != nil {
@@ -125,7 +126,7 @@ func decodePutJSON(body io.Reader) (zapcore.Level, error) {
 		return 0, fmt.Errorf("malformed request body: %v", err)
 	}
 	if pld.Level == nil {
-		return 0, fmt.Errorf("must specify logging level")
+		return 0, errors.New("must specify logging level")
 	}
 	return *pld.Level, nil
 
diff --git a/vendor/go.uber.org/zap/internal/exit/exit.go b/vendor/go.uber.org/zap/internal/exit/exit.go
index dfc5b05fe..f673f9947 100644
--- a/vendor/go.uber.org/zap/internal/exit/exit.go
+++ b/vendor/go.uber.org/zap/internal/exit/exit.go
@@ -24,24 +24,25 @@ package exit
 
 import "os"
 
-var real = func() { os.Exit(1) }
+var _exit = os.Exit
 
-// Exit normally terminates the process by calling os.Exit(1). If the package
-// is stubbed, it instead records a call in the testing spy.
-func Exit() {
-	real()
+// With terminates the process by calling os.Exit(code). If the package is
+// stubbed, it instead records a call in the testing spy.
+func With(code int) {
+	_exit(code)
 }
 
 // A StubbedExit is a testing fake for os.Exit.
 type StubbedExit struct {
 	Exited bool
-	prev   func()
+	Code   int
+	prev   func(code int)
 }
 
 // Stub substitutes a fake for the call to os.Exit(1).
 func Stub() *StubbedExit {
-	s := &StubbedExit{prev: real}
-	real = s.exit
+	s := &StubbedExit{prev: _exit}
+	_exit = s.exit
 	return s
 }
 
@@ -56,9 +57,10 @@ func WithStub(f func()) *StubbedExit {
 
 // Unstub restores the previous exit function.
 func (se *StubbedExit) Unstub() {
-	real = se.prev
+	_exit = se.prev
 }
 
-func (se *StubbedExit) exit() {
+func (se *StubbedExit) exit(code int) {
 	se.Exited = true
+	se.Code = code
 }
diff --git a/vendor/go.uber.org/zap/global_go112.go b/vendor/go.uber.org/zap/internal/level_enabler.go
similarity index 70%
rename from vendor/go.uber.org/zap/global_go112.go
rename to vendor/go.uber.org/zap/internal/level_enabler.go
index 6b5dbda80..5f3e3f1b9 100644
--- a/vendor/go.uber.org/zap/global_go112.go
+++ b/vendor/go.uber.org/zap/internal/level_enabler.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 Uber Technologies, Inc.
+// Copyright (c) 2022 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
@@ -18,9 +18,18 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-// See #682 for more information.
-// +build go1.12
+package internal
 
-package zap
+import "go.uber.org/zap/zapcore"
 
-const _stdLogDefaultDepth = 1
+// LeveledEnabler is an interface satisfied by LevelEnablers that are able to
+// report their own level.
+//
+// This interface is defined to use more conveniently in tests and non-zapcore
+// packages.
+// This cannot be imported from zapcore because of the cyclic dependency.
+type LeveledEnabler interface {
+	zapcore.LevelEnabler
+
+	Level() zapcore.Level
+}
diff --git a/vendor/go.uber.org/zap/level.go b/vendor/go.uber.org/zap/level.go
index 3567a9a1e..db951e19a 100644
--- a/vendor/go.uber.org/zap/level.go
+++ b/vendor/go.uber.org/zap/level.go
@@ -22,6 +22,7 @@ package zap
 
 import (
 	"go.uber.org/atomic"
+	"go.uber.org/zap/internal"
 	"go.uber.org/zap/zapcore"
 )
 
@@ -70,6 +71,8 @@ type AtomicLevel struct {
 	l *atomic.Int32
 }
 
+var _ internal.LeveledEnabler = AtomicLevel{}
+
 // NewAtomicLevel creates an AtomicLevel with InfoLevel and above logging
 // enabled.
 func NewAtomicLevel() AtomicLevel {
@@ -86,6 +89,23 @@ func NewAtomicLevelAt(l zapcore.Level) AtomicLevel {
 	return a
 }
 
+// ParseAtomicLevel parses an AtomicLevel based on a lowercase or all-caps ASCII
+// representation of the log level. If the provided ASCII representation is
+// invalid an error is returned.
+//
+// This is particularly useful when dealing with text input to configure log
+// levels.
+func ParseAtomicLevel(text string) (AtomicLevel, error) {
+	a := NewAtomicLevel()
+	l, err := zapcore.ParseLevel(text)
+	if err != nil {
+		return a, err
+	}
+
+	a.SetLevel(l)
+	return a, nil
+}
+
 // Enabled implements the zapcore.LevelEnabler interface, which allows the
 // AtomicLevel to be used in place of traditional static levels.
 func (lvl AtomicLevel) Enabled(l zapcore.Level) bool {
diff --git a/vendor/go.uber.org/zap/logger.go b/vendor/go.uber.org/zap/logger.go
index f116bd936..cd44030d1 100644
--- a/vendor/go.uber.org/zap/logger.go
+++ b/vendor/go.uber.org/zap/logger.go
@@ -22,11 +22,11 @@ package zap
 
 import (
 	"fmt"
-	"io/ioutil"
+	"io"
 	"os"
-	"runtime"
 	"strings"
 
+	"go.uber.org/zap/internal/bufferpool"
 	"go.uber.org/zap/zapcore"
 )
 
@@ -42,7 +42,7 @@ type Logger struct {
 
 	development bool
 	addCaller   bool
-	onFatal     zapcore.CheckWriteAction // default is WriteThenFatal
+	onFatal     zapcore.CheckWriteHook // default is WriteThenFatal
 
 	name        string
 	errorOutput zapcore.WriteSyncer
@@ -85,7 +85,7 @@ func New(core zapcore.Core, options ...Option) *Logger {
 func NewNop() *Logger {
 	return &Logger{
 		core:        zapcore.NewNopCore(),
-		errorOutput: zapcore.AddSync(ioutil.Discard),
+		errorOutput: zapcore.AddSync(io.Discard),
 		addStack:    zapcore.FatalLevel + 1,
 		clock:       zapcore.DefaultClock,
 	}
@@ -107,6 +107,19 @@ func NewDevelopment(options ...Option) (*Logger, error) {
 	return NewDevelopmentConfig().Build(options...)
 }
 
+// Must is a helper that wraps a call to a function returning (*Logger, error)
+// and panics if the error is non-nil. It is intended for use in variable
+// initialization such as:
+//
+//	var logger = zap.Must(zap.NewProduction())
+func Must(logger *Logger, err error) *Logger {
+	if err != nil {
+		panic(err)
+	}
+
+	return logger
+}
+
 // NewExample builds a Logger that's designed for use in zap's testable
 // examples. It writes DebugLevel and above logs to standard out as JSON, but
 // omits the timestamp and calling function to keep example output
@@ -170,6 +183,13 @@ func (log *Logger) With(fields ...Field) *Logger {
 	return l
 }
 
+// Level reports the minimum enabled level for this logger.
+//
+// For NopLoggers, this is [zapcore.InvalidLevel].
+func (log *Logger) Level() zapcore.Level {
+	return zapcore.LevelOf(log.core)
+}
+
 // Check returns a CheckedEntry if logging a message at the specified level
 // is enabled. It's a completely optional optimization; in high-performance
 // applications, Check can help avoid allocating a slice to hold fields.
@@ -177,6 +197,14 @@ func (log *Logger) Check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
 	return log.check(lvl, msg)
 }
 
+// Log logs a message at the specified level. The message includes any fields
+// passed at the log site, as well as any fields accumulated on the logger.
+func (log *Logger) Log(lvl zapcore.Level, msg string, fields ...Field) {
+	if ce := log.check(lvl, msg); ce != nil {
+		ce.Write(fields...)
+	}
+}
+
 // Debug logs a message at DebugLevel. The message includes any fields passed
 // at the log site, as well as any fields accumulated on the logger.
 func (log *Logger) Debug(msg string, fields ...Field) {
@@ -259,8 +287,10 @@ func (log *Logger) clone() *Logger {
 }
 
 func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
-	// check must always be called directly by a method in the Logger interface
-	// (e.g., Check, Info, Fatal).
+	// Logger.check must always be called directly by a method in the
+	// Logger interface (e.g., Check, Info, Fatal).
+	// This skips Logger.check and the Info/Fatal/Check/etc. method that
+	// called it.
 	const callerSkipOffset = 2
 
 	// Check the level first to reduce the cost of disabled log calls.
@@ -283,18 +313,27 @@ func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
 	// Set up any required terminal behavior.
 	switch ent.Level {
 	case zapcore.PanicLevel:
-		ce = ce.Should(ent, zapcore.WriteThenPanic)
+		ce = ce.After(ent, zapcore.WriteThenPanic)
 	case zapcore.FatalLevel:
 		onFatal := log.onFatal
-		// Noop is the default value for CheckWriteAction, and it leads to
-		// continued execution after a Fatal which is unexpected.
-		if onFatal == zapcore.WriteThenNoop {
+		// nil or WriteThenNoop will lead to continued execution after
+		// a Fatal log entry, which is unexpected. For example,
+		//
+		//   f, err := os.Open(..)
+		//   if err != nil {
+		//     log.Fatal("cannot open", zap.Error(err))
+		//   }
+		//   fmt.Println(f.Name())
+		//
+		// The f.Name() will panic if we continue execution after the
+		// log.Fatal.
+		if onFatal == nil || onFatal == zapcore.WriteThenNoop {
 			onFatal = zapcore.WriteThenFatal
 		}
-		ce = ce.Should(ent, onFatal)
+		ce = ce.After(ent, onFatal)
 	case zapcore.DPanicLevel:
 		if log.development {
-			ce = ce.Should(ent, zapcore.WriteThenPanic)
+			ce = ce.After(ent, zapcore.WriteThenPanic)
 		}
 	}
 
@@ -307,42 +346,55 @@ func (log *Logger) check(lvl zapcore.Level, msg string) *zapcore.CheckedEntry {
 
 	// Thread the error output through to the CheckedEntry.
 	ce.ErrorOutput = log.errorOutput
-	if log.addCaller {
-		frame, defined := getCallerFrame(log.callerSkip + callerSkipOffset)
-		if !defined {
+
+	addStack := log.addStack.Enabled(ce.Level)
+	if !log.addCaller && !addStack {
+		return ce
+	}
+
+	// Adding the caller or stack trace requires capturing the callers of
+	// this function. We'll share information between these two.
+	stackDepth := stacktraceFirst
+	if addStack {
+		stackDepth = stacktraceFull
+	}
+	stack := captureStacktrace(log.callerSkip+callerSkipOffset, stackDepth)
+	defer stack.Free()
+
+	if stack.Count() == 0 {
+		if log.addCaller {
 			fmt.Fprintf(log.errorOutput, "%v Logger.check error: failed to get caller\n", ent.Time.UTC())
 			log.errorOutput.Sync()
 		}
+		return ce
+	}
 
-		ce.Entry.Caller = zapcore.EntryCaller{
-			Defined:  defined,
+	frame, more := stack.Next()
+
+	if log.addCaller {
+		ce.Caller = zapcore.EntryCaller{
+			Defined:  frame.PC != 0,
 			PC:       frame.PC,
 			File:     frame.File,
 			Line:     frame.Line,
 			Function: frame.Function,
 		}
 	}
-	if log.addStack.Enabled(ce.Entry.Level) {
-		ce.Entry.Stack = StackSkip("", log.callerSkip+callerSkipOffset).String
-	}
 
-	return ce
-}
+	if addStack {
+		buffer := bufferpool.Get()
+		defer buffer.Free()
 
-// getCallerFrame gets caller frame. The argument skip is the number of stack
-// frames to ascend, with 0 identifying the caller of getCallerFrame. The
-// boolean ok is false if it was not possible to recover the information.
-//
-// Note: This implementation is similar to runtime.Caller, but it returns the whole frame.
-func getCallerFrame(skip int) (frame runtime.Frame, ok bool) {
-	const skipOffset = 2 // skip getCallerFrame and Callers
-
-	pc := make([]uintptr, 1)
-	numFrames := runtime.Callers(skip+skipOffset, pc)
-	if numFrames < 1 {
-		return
+		stackfmt := newStackFormatter(buffer)
+
+		// We've already extracted the first frame, so format that
+		// separately and defer to stackfmt for the rest.
+		stackfmt.FormatFrame(frame)
+		if more {
+			stackfmt.FormatStack(stack)
+		}
+		ce.Stack = buffer.String()
 	}
 
-	frame, _ = runtime.CallersFrames(pc).Next()
-	return frame, frame.PC != 0
+	return ce
 }
diff --git a/vendor/go.uber.org/zap/options.go b/vendor/go.uber.org/zap/options.go
index e9e66161f..c4f3bca3d 100644
--- a/vendor/go.uber.org/zap/options.go
+++ b/vendor/go.uber.org/zap/options.go
@@ -133,9 +133,28 @@ func IncreaseLevel(lvl zapcore.LevelEnabler) Option {
 }
 
 // OnFatal sets the action to take on fatal logs.
+//
+// Deprecated: Use [WithFatalHook] instead.
 func OnFatal(action zapcore.CheckWriteAction) Option {
+	return WithFatalHook(action)
+}
+
+// WithFatalHook sets a CheckWriteHook to run on fatal logs.
+// Zap will call this hook after writing a log statement with a Fatal level.
+//
+// For example, the following builds a logger that will exit the current
+// goroutine after writing a fatal log message, but it will not exit the
+// program.
+//
+//	zap.New(core, zap.WithFatalHook(zapcore.WriteThenGoexit))
+//
+// It is important that the provided CheckWriteHook stops the control flow at
+// the current statement to meet expectations of callers of the logger.
+// We recommend calling os.Exit or runtime.Goexit inside custom hooks at
+// minimum.
+func WithFatalHook(hook zapcore.CheckWriteHook) Option {
 	return optionFunc(func(log *Logger) {
-		log.onFatal = action
+		log.onFatal = hook
 	})
 }
 
diff --git a/vendor/go.uber.org/zap/sink.go b/vendor/go.uber.org/zap/sink.go
index df46fa87a..478c9a10f 100644
--- a/vendor/go.uber.org/zap/sink.go
+++ b/vendor/go.uber.org/zap/sink.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
+// Copyright (c) 2016-2022 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
@@ -26,6 +26,7 @@ import (
 	"io"
 	"net/url"
 	"os"
+	"path/filepath"
 	"strings"
 	"sync"
 
@@ -34,23 +35,7 @@ import (
 
 const schemeFile = "file"
 
-var (
-	_sinkMutex     sync.RWMutex
-	_sinkFactories map[string]func(*url.URL) (Sink, error) // keyed by scheme
-)
-
-func init() {
-	resetSinkRegistry()
-}
-
-func resetSinkRegistry() {
-	_sinkMutex.Lock()
-	defer _sinkMutex.Unlock()
-
-	_sinkFactories = map[string]func(*url.URL) (Sink, error){
-		schemeFile: newFileSink,
-	}
-}
+var _sinkRegistry = newSinkRegistry()
 
 // Sink defines the interface to write to and close logger destinations.
 type Sink interface {
@@ -58,10 +43,6 @@ type Sink interface {
 	io.Closer
 }
 
-type nopCloserSink struct{ zapcore.WriteSyncer }
-
-func (nopCloserSink) Close() error { return nil }
-
 type errSinkNotFound struct {
 	scheme string
 }
@@ -70,16 +51,29 @@ func (e *errSinkNotFound) Error() string {
 	return fmt.Sprintf("no sink found for scheme %q", e.scheme)
 }
 
-// RegisterSink registers a user-supplied factory for all sinks with a
-// particular scheme.
-//
-// All schemes must be ASCII, valid under section 3.1 of RFC 3986
-// (https://tools.ietf.org/html/rfc3986#section-3.1), and must not already
-// have a factory registered. Zap automatically registers a factory for the
-// "file" scheme.
-func RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) error {
-	_sinkMutex.Lock()
-	defer _sinkMutex.Unlock()
+type nopCloserSink struct{ zapcore.WriteSyncer }
+
+func (nopCloserSink) Close() error { return nil }
+
+type sinkRegistry struct {
+	mu        sync.Mutex
+	factories map[string]func(*url.URL) (Sink, error)          // keyed by scheme
+	openFile  func(string, int, os.FileMode) (*os.File, error) // type matches os.OpenFile
+}
+
+func newSinkRegistry() *sinkRegistry {
+	sr := &sinkRegistry{
+		factories: make(map[string]func(*url.URL) (Sink, error)),
+		openFile:  os.OpenFile,
+	}
+	sr.RegisterSink(schemeFile, sr.newFileSinkFromURL)
+	return sr
+}
+
+// RegisterScheme registers the given factory for the specific scheme.
+func (sr *sinkRegistry) RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) error {
+	sr.mu.Lock()
+	defer sr.mu.Unlock()
 
 	if scheme == "" {
 		return errors.New("can't register a sink factory for empty string")
@@ -88,14 +82,22 @@ func RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) error {
 	if err != nil {
 		return fmt.Errorf("%q is not a valid scheme: %v", scheme, err)
 	}
-	if _, ok := _sinkFactories[normalized]; ok {
+	if _, ok := sr.factories[normalized]; ok {
 		return fmt.Errorf("sink factory already registered for scheme %q", normalized)
 	}
-	_sinkFactories[normalized] = factory
+	sr.factories[normalized] = factory
 	return nil
 }
 
-func newSink(rawURL string) (Sink, error) {
+func (sr *sinkRegistry) newSink(rawURL string) (Sink, error) {
+	// URL parsing doesn't work well for Windows paths such as `c:\log.txt`, as scheme is set to
+	// the drive, and path is unset unless `c:/log.txt` is used.
+	// To avoid Windows-specific URL handling, we instead check IsAbs to open as a file.
+	// filepath.IsAbs is OS-specific, so IsAbs('c:/log.txt') is false outside of Windows.
+	if filepath.IsAbs(rawURL) {
+		return sr.newFileSinkFromPath(rawURL)
+	}
+
 	u, err := url.Parse(rawURL)
 	if err != nil {
 		return nil, fmt.Errorf("can't parse %q as a URL: %v", rawURL, err)
@@ -104,16 +106,27 @@ func newSink(rawURL string) (Sink, error) {
 		u.Scheme = schemeFile
 	}
 
-	_sinkMutex.RLock()
-	factory, ok := _sinkFactories[u.Scheme]
-	_sinkMutex.RUnlock()
+	sr.mu.Lock()
+	factory, ok := sr.factories[u.Scheme]
+	sr.mu.Unlock()
 	if !ok {
 		return nil, &errSinkNotFound{u.Scheme}
 	}
 	return factory(u)
 }
 
-func newFileSink(u *url.URL) (Sink, error) {
+// RegisterSink registers a user-supplied factory for all sinks with a
+// particular scheme.
+//
+// All schemes must be ASCII, valid under section 0.1 of RFC 3986
+// (https://tools.ietf.org/html/rfc3983#section-3.1), and must not already
+// have a factory registered. Zap automatically registers a factory for the
+// "file" scheme.
+func RegisterSink(scheme string, factory func(*url.URL) (Sink, error)) error {
+	return _sinkRegistry.RegisterSink(scheme, factory)
+}
+
+func (sr *sinkRegistry) newFileSinkFromURL(u *url.URL) (Sink, error) {
 	if u.User != nil {
 		return nil, fmt.Errorf("user and password not allowed with file URLs: got %v", u)
 	}
@@ -130,13 +143,18 @@ func newFileSink(u *url.URL) (Sink, error) {
 	if hn := u.Hostname(); hn != "" && hn != "localhost" {
 		return nil, fmt.Errorf("file URLs must leave host empty or use localhost: got %v", u)
 	}
-	switch u.Path {
+
+	return sr.newFileSinkFromPath(u.Path)
+}
+
+func (sr *sinkRegistry) newFileSinkFromPath(path string) (Sink, error) {
+	switch path {
 	case "stdout":
 		return nopCloserSink{os.Stdout}, nil
 	case "stderr":
 		return nopCloserSink{os.Stderr}, nil
 	}
-	return os.OpenFile(u.Path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
+	return sr.openFile(path, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
 }
 
 func normalizeScheme(s string) (string, error) {
diff --git a/vendor/go.uber.org/zap/stacktrace.go b/vendor/go.uber.org/zap/stacktrace.go
index 0cf8c1ddf..817a3bde8 100644
--- a/vendor/go.uber.org/zap/stacktrace.go
+++ b/vendor/go.uber.org/zap/stacktrace.go
@@ -24,62 +24,153 @@ import (
 	"runtime"
 	"sync"
 
+	"go.uber.org/zap/buffer"
 	"go.uber.org/zap/internal/bufferpool"
 )
 
-var (
-	_stacktracePool = sync.Pool{
-		New: func() interface{} {
-			return newProgramCounters(64)
-		},
-	}
+var _stacktracePool = sync.Pool{
+	New: func() interface{} {
+		return &stacktrace{
+			storage: make([]uintptr, 64),
+		}
+	},
+}
+
+type stacktrace struct {
+	pcs    []uintptr // program counters; always a subslice of storage
+	frames *runtime.Frames
+
+	// The size of pcs varies depending on requirements:
+	// it will be one if the only the first frame was requested,
+	// and otherwise it will reflect the depth of the call stack.
+	//
+	// storage decouples the slice we need (pcs) from the slice we pool.
+	// We will always allocate a reasonably large storage, but we'll use
+	// only as much of it as we need.
+	storage []uintptr
+}
+
+// stacktraceDepth specifies how deep of a stack trace should be captured.
+type stacktraceDepth int
+
+const (
+	// stacktraceFirst captures only the first frame.
+	stacktraceFirst stacktraceDepth = iota
+
+	// stacktraceFull captures the entire call stack, allocating more
+	// storage for it if needed.
+	stacktraceFull
 )
 
-func takeStacktrace(skip int) string {
-	buffer := bufferpool.Get()
-	defer buffer.Free()
-	programCounters := _stacktracePool.Get().(*programCounters)
-	defer _stacktracePool.Put(programCounters)
-
-	var numFrames int
-	for {
-		// Skip the call to runtime.Callers and takeStacktrace so that the
-		// program counters start at the caller of takeStacktrace.
-		numFrames = runtime.Callers(skip+2, programCounters.pcs)
-		if numFrames < len(programCounters.pcs) {
-			break
-		}
-		// Don't put the too-short counter slice back into the pool; this lets
-		// the pool adjust if we consistently take deep stacktraces.
-		programCounters = newProgramCounters(len(programCounters.pcs) * 2)
+// captureStacktrace captures a stack trace of the specified depth, skipping
+// the provided number of frames. skip=0 identifies the caller of
+// captureStacktrace.
+//
+// The caller must call Free on the returned stacktrace after using it.
+func captureStacktrace(skip int, depth stacktraceDepth) *stacktrace {
+	stack := _stacktracePool.Get().(*stacktrace)
+
+	switch depth {
+	case stacktraceFirst:
+		stack.pcs = stack.storage[:1]
+	case stacktraceFull:
+		stack.pcs = stack.storage
 	}
 
-	i := 0
-	frames := runtime.CallersFrames(programCounters.pcs[:numFrames])
+	// Unlike other "skip"-based APIs, skip=0 identifies runtime.Callers
+	// itself. +2 to skip captureStacktrace and runtime.Callers.
+	numFrames := runtime.Callers(
+		skip+2,
+		stack.pcs,
+	)
 
-	// Note: On the last iteration, frames.Next() returns false, with a valid
-	// frame, but we ignore this frame. The last frame is a a runtime frame which
-	// adds noise, since it's only either runtime.main or runtime.goexit.
-	for frame, more := frames.Next(); more; frame, more = frames.Next() {
-		if i != 0 {
-			buffer.AppendByte('\n')
+	// runtime.Callers truncates the recorded stacktrace if there is no
+	// room in the provided slice. For the full stack trace, keep expanding
+	// storage until there are fewer frames than there is room.
+	if depth == stacktraceFull {
+		pcs := stack.pcs
+		for numFrames == len(pcs) {
+			pcs = make([]uintptr, len(pcs)*2)
+			numFrames = runtime.Callers(skip+2, pcs)
 		}
-		i++
-		buffer.AppendString(frame.Function)
-		buffer.AppendByte('\n')
-		buffer.AppendByte('\t')
-		buffer.AppendString(frame.File)
-		buffer.AppendByte(':')
-		buffer.AppendInt(int64(frame.Line))
+
+		// Discard old storage instead of returning it to the pool.
+		// This will adjust the pool size over time if stack traces are
+		// consistently very deep.
+		stack.storage = pcs
+		stack.pcs = pcs[:numFrames]
+	} else {
+		stack.pcs = stack.pcs[:numFrames]
 	}
 
+	stack.frames = runtime.CallersFrames(stack.pcs)
+	return stack
+}
+
+// Free releases resources associated with this stacktrace
+// and returns it back to the pool.
+func (st *stacktrace) Free() {
+	st.frames = nil
+	st.pcs = nil
+	_stacktracePool.Put(st)
+}
+
+// Count reports the total number of frames in this stacktrace.
+// Count DOES NOT change as Next is called.
+func (st *stacktrace) Count() int {
+	return len(st.pcs)
+}
+
+// Next returns the next frame in the stack trace,
+// and a boolean indicating whether there are more after it.
+func (st *stacktrace) Next() (_ runtime.Frame, more bool) {
+	return st.frames.Next()
+}
+
+func takeStacktrace(skip int) string {
+	stack := captureStacktrace(skip+1, stacktraceFull)
+	defer stack.Free()
+
+	buffer := bufferpool.Get()
+	defer buffer.Free()
+
+	stackfmt := newStackFormatter(buffer)
+	stackfmt.FormatStack(stack)
 	return buffer.String()
 }
 
-type programCounters struct {
-	pcs []uintptr
+// stackFormatter formats a stack trace into a readable string representation.
+type stackFormatter struct {
+	b        *buffer.Buffer
+	nonEmpty bool // whehther we've written at least one frame already
+}
+
+// newStackFormatter builds a new stackFormatter.
+func newStackFormatter(b *buffer.Buffer) stackFormatter {
+	return stackFormatter{b: b}
 }
 
-func newProgramCounters(size int) *programCounters {
-	return &programCounters{make([]uintptr, size)}
+// FormatStack formats all remaining frames in the provided stacktrace -- minus
+// the final runtime.main/runtime.goexit frame.
+func (sf *stackFormatter) FormatStack(stack *stacktrace) {
+	// Note: On the last iteration, frames.Next() returns false, with a valid
+	// frame, but we ignore this frame. The last frame is a runtime frame which
+	// adds noise, since it's only either runtime.main or runtime.goexit.
+	for frame, more := stack.Next(); more; frame, more = stack.Next() {
+		sf.FormatFrame(frame)
+	}
+}
+
+// FormatFrame formats the given frame.
+func (sf *stackFormatter) FormatFrame(frame runtime.Frame) {
+	if sf.nonEmpty {
+		sf.b.AppendByte('\n')
+	}
+	sf.nonEmpty = true
+	sf.b.AppendString(frame.Function)
+	sf.b.AppendByte('\n')
+	sf.b.AppendByte('\t')
+	sf.b.AppendString(frame.File)
+	sf.b.AppendByte(':')
+	sf.b.AppendInt(int64(frame.Line))
 }
diff --git a/vendor/go.uber.org/zap/sugar.go b/vendor/go.uber.org/zap/sugar.go
index 0b9651981..ac387b3e4 100644
--- a/vendor/go.uber.org/zap/sugar.go
+++ b/vendor/go.uber.org/zap/sugar.go
@@ -31,6 +31,7 @@ import (
 const (
 	_oddNumberErrMsg    = "Ignored key without a value."
 	_nonStringKeyErrMsg = "Ignored key-value pairs with non-string keys."
+	_multipleErrMsg     = "Multiple errors without a key."
 )
 
 // A SugaredLogger wraps the base Logger functionality in a slower, but less
@@ -38,10 +39,19 @@ const (
 // method.
 //
 // Unlike the Logger, the SugaredLogger doesn't insist on structured logging.
-// For each log level, it exposes three methods: one for loosely-typed
-// structured logging, one for println-style formatting, and one for
-// printf-style formatting. For example, SugaredLoggers can produce InfoLevel
-// output with Infow ("info with" structured context), Info, or Infof.
+// For each log level, it exposes four methods:
+//
+//   - methods named after the log level for log.Print-style logging
+//   - methods ending in "w" for loosely-typed structured logging
+//   - methods ending in "f" for log.Printf-style logging
+//   - methods ending in "ln" for log.Println-style logging
+//
+// For example, the methods for InfoLevel are:
+//
+//	Info(...any)           Print-style logging
+//	Infow(...any)          Structured logging (read as "info with")
+//	Infof(string, ...any)  Printf-style logging
+//	Infoln(...any)         Println-style logging
 type SugaredLogger struct {
 	base *Logger
 }
@@ -61,27 +71,40 @@ func (s *SugaredLogger) Named(name string) *SugaredLogger {
 	return &SugaredLogger{base: s.base.Named(name)}
 }
 
+// WithOptions clones the current SugaredLogger, applies the supplied Options,
+// and returns the result. It's safe to use concurrently.
+func (s *SugaredLogger) WithOptions(opts ...Option) *SugaredLogger {
+	base := s.base.clone()
+	for _, opt := range opts {
+		opt.apply(base)
+	}
+	return &SugaredLogger{base: base}
+}
+
 // With adds a variadic number of fields to the logging context. It accepts a
 // mix of strongly-typed Field objects and loosely-typed key-value pairs. When
 // processing pairs, the first element of the pair is used as the field key
 // and the second as the field value.
 //
 // For example,
-//   sugaredLogger.With(
-//     "hello", "world",
-//     "failure", errors.New("oh no"),
-//     Stack(),
-//     "count", 42,
-//     "user", User{Name: "alice"},
-//  )
+//
+//	 sugaredLogger.With(
+//	   "hello", "world",
+//	   "failure", errors.New("oh no"),
+//	   Stack(),
+//	   "count", 42,
+//	   "user", User{Name: "alice"},
+//	)
+//
 // is the equivalent of
-//   unsugared.With(
-//     String("hello", "world"),
-//     String("failure", "oh no"),
-//     Stack(),
-//     Int("count", 42),
-//     Object("user", User{Name: "alice"}),
-//   )
+//
+//	unsugared.With(
+//	  String("hello", "world"),
+//	  String("failure", "oh no"),
+//	  Stack(),
+//	  Int("count", 42),
+//	  Object("user", User{Name: "alice"}),
+//	)
 //
 // Note that the keys in key-value pairs should be strings. In development,
 // passing a non-string key panics. In production, the logger is more
@@ -92,6 +115,13 @@ func (s *SugaredLogger) With(args ...interface{}) *SugaredLogger {
 	return &SugaredLogger{base: s.base.With(s.sweetenFields(args)...)}
 }
 
+// Level reports the minimum enabled level for this logger.
+//
+// For NopLoggers, this is [zapcore.InvalidLevel].
+func (s *SugaredLogger) Level() zapcore.Level {
+	return zapcore.LevelOf(s.base.core)
+}
+
 // Debug uses fmt.Sprint to construct and log a message.
 func (s *SugaredLogger) Debug(args ...interface{}) {
 	s.log(DebugLevel, "", args, nil)
@@ -168,7 +198,8 @@ func (s *SugaredLogger) Fatalf(template string, args ...interface{}) {
 // pairs are treated as they are in With.
 //
 // When debug-level logging is disabled, this is much faster than
-//  s.With(keysAndValues).Debug(msg)
+//
+//	s.With(keysAndValues).Debug(msg)
 func (s *SugaredLogger) Debugw(msg string, keysAndValues ...interface{}) {
 	s.log(DebugLevel, msg, nil, keysAndValues)
 }
@@ -210,11 +241,48 @@ func (s *SugaredLogger) Fatalw(msg string, keysAndValues ...interface{}) {
 	s.log(FatalLevel, msg, nil, keysAndValues)
 }
 
+// Debugln uses fmt.Sprintln to construct and log a message.
+func (s *SugaredLogger) Debugln(args ...interface{}) {
+	s.logln(DebugLevel, args, nil)
+}
+
+// Infoln uses fmt.Sprintln to construct and log a message.
+func (s *SugaredLogger) Infoln(args ...interface{}) {
+	s.logln(InfoLevel, args, nil)
+}
+
+// Warnln uses fmt.Sprintln to construct and log a message.
+func (s *SugaredLogger) Warnln(args ...interface{}) {
+	s.logln(WarnLevel, args, nil)
+}
+
+// Errorln uses fmt.Sprintln to construct and log a message.
+func (s *SugaredLogger) Errorln(args ...interface{}) {
+	s.logln(ErrorLevel, args, nil)
+}
+
+// DPanicln uses fmt.Sprintln to construct and log a message. In development, the
+// logger then panics. (See DPanicLevel for details.)
+func (s *SugaredLogger) DPanicln(args ...interface{}) {
+	s.logln(DPanicLevel, args, nil)
+}
+
+// Panicln uses fmt.Sprintln to construct and log a message, then panics.
+func (s *SugaredLogger) Panicln(args ...interface{}) {
+	s.logln(PanicLevel, args, nil)
+}
+
+// Fatalln uses fmt.Sprintln to construct and log a message, then calls os.Exit.
+func (s *SugaredLogger) Fatalln(args ...interface{}) {
+	s.logln(FatalLevel, args, nil)
+}
+
 // Sync flushes any buffered log entries.
 func (s *SugaredLogger) Sync() error {
 	return s.base.Sync()
 }
 
+// log message with Sprint, Sprintf, or neither.
 func (s *SugaredLogger) log(lvl zapcore.Level, template string, fmtArgs []interface{}, context []interface{}) {
 	// If logging at this level is completely disabled, skip the overhead of
 	// string formatting.
@@ -228,6 +296,18 @@ func (s *SugaredLogger) log(lvl zapcore.Level, template string, fmtArgs []interf
 	}
 }
 
+// logln message with Sprintln
+func (s *SugaredLogger) logln(lvl zapcore.Level, fmtArgs []interface{}, context []interface{}) {
+	if lvl < DPanicLevel && !s.base.Core().Enabled(lvl) {
+		return
+	}
+
+	msg := getMessageln(fmtArgs)
+	if ce := s.base.Check(lvl, msg); ce != nil {
+		ce.Write(s.sweetenFields(context)...)
+	}
+}
+
 // getMessage format with Sprint, Sprintf, or neither.
 func getMessage(template string, fmtArgs []interface{}) string {
 	if len(fmtArgs) == 0 {
@@ -246,15 +326,24 @@ func getMessage(template string, fmtArgs []interface{}) string {
 	return fmt.Sprint(fmtArgs...)
 }
 
+// getMessageln format with Sprintln.
+func getMessageln(fmtArgs []interface{}) string {
+	msg := fmt.Sprintln(fmtArgs...)
+	return msg[:len(msg)-1]
+}
+
 func (s *SugaredLogger) sweetenFields(args []interface{}) []Field {
 	if len(args) == 0 {
 		return nil
 	}
 
-	// Allocate enough space for the worst case; if users pass only structured
-	// fields, we shouldn't penalize them with extra allocations.
-	fields := make([]Field, 0, len(args))
-	var invalid invalidPairs
+	var (
+		// Allocate enough space for the worst case; if users pass only structured
+		// fields, we shouldn't penalize them with extra allocations.
+		fields    = make([]Field, 0, len(args))
+		invalid   invalidPairs
+		seenError bool
+	)
 
 	for i := 0; i < len(args); {
 		// This is a strongly-typed field. Consume it and move on.
@@ -264,6 +353,18 @@ func (s *SugaredLogger) sweetenFields(args []interface{}) []Field {
 			continue
 		}
 
+		// If it is an error, consume it and move on.
+		if err, ok := args[i].(error); ok {
+			if !seenError {
+				seenError = true
+				fields = append(fields, Error(err))
+			} else {
+				s.base.Error(_multipleErrMsg, Error(err))
+			}
+			i++
+			continue
+		}
+
 		// Make sure this element isn't a dangling key.
 		if i == len(args)-1 {
 			s.base.Error(_oddNumberErrMsg, Any("ignored", args[i]))
diff --git a/vendor/go.uber.org/zap/writer.go b/vendor/go.uber.org/zap/writer.go
index 86a709ab0..f08728e1e 100644
--- a/vendor/go.uber.org/zap/writer.go
+++ b/vendor/go.uber.org/zap/writer.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
+// Copyright (c) 2016-2022 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
@@ -23,7 +23,6 @@ package zap
 import (
 	"fmt"
 	"io"
-	"io/ioutil"
 
 	"go.uber.org/zap/zapcore"
 
@@ -69,9 +68,9 @@ func open(paths []string) ([]zapcore.WriteSyncer, func(), error) {
 
 	var openErr error
 	for _, path := range paths {
-		sink, err := newSink(path)
+		sink, err := _sinkRegistry.newSink(path)
 		if err != nil {
-			openErr = multierr.Append(openErr, fmt.Errorf("couldn't open sink %q: %v", path, err))
+			openErr = multierr.Append(openErr, fmt.Errorf("open sink %q: %w", path, err))
 			continue
 		}
 		writers = append(writers, sink)
@@ -79,7 +78,7 @@ func open(paths []string) ([]zapcore.WriteSyncer, func(), error) {
 	}
 	if openErr != nil {
 		close()
-		return writers, nil, openErr
+		return nil, nil, openErr
 	}
 
 	return writers, close, nil
@@ -93,7 +92,7 @@ func open(paths []string) ([]zapcore.WriteSyncer, func(), error) {
 // using zapcore.NewMultiWriteSyncer and zapcore.Lock individually.
 func CombineWriteSyncers(writers ...zapcore.WriteSyncer) zapcore.WriteSyncer {
 	if len(writers) == 0 {
-		return zapcore.AddSync(ioutil.Discard)
+		return zapcore.AddSync(io.Discard)
 	}
 	return zapcore.Lock(zapcore.NewMultiWriteSyncer(writers...))
 }
diff --git a/vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go b/vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go
index ef2f7d963..a40e93b3e 100644
--- a/vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go
+++ b/vendor/go.uber.org/zap/zapcore/buffered_write_syncer.go
@@ -43,6 +43,37 @@ const (
 //
 // BufferedWriteSyncer is safe for concurrent use. You don't need to use
 // zapcore.Lock for WriteSyncers with BufferedWriteSyncer.
+//
+// To set up a BufferedWriteSyncer, construct a WriteSyncer for your log
+// destination (*os.File is a valid WriteSyncer), wrap it with
+// BufferedWriteSyncer, and defer a Stop() call for when you no longer need the
+// object.
+//
+//	 func main() {
+//	   ws := ... // your log destination
+//	   bws := &zapcore.BufferedWriteSyncer{WS: ws}
+//	   defer bws.Stop()
+//
+//	   // ...
+//	   core := zapcore.NewCore(enc, bws, lvl)
+//	   logger := zap.New(core)
+//
+//	   // ...
+//	}
+//
+// By default, a BufferedWriteSyncer will buffer up to 256 kilobytes of logs,
+// waiting at most 30 seconds between flushes.
+// You can customize these parameters by setting the Size or FlushInterval
+// fields.
+// For example, the following buffers up to 512 kB of logs before flushing them
+// to Stderr, with a maximum of one minute between each flush.
+//
+//	ws := &BufferedWriteSyncer{
+//	  WS:            os.Stderr,
+//	  Size:          512 * 1024, // 512 kB
+//	  FlushInterval: time.Minute,
+//	}
+//	defer ws.Stop()
 type BufferedWriteSyncer struct {
 	// WS is the WriteSyncer around which BufferedWriteSyncer will buffer
 	// writes.
diff --git a/vendor/go.uber.org/zap/zapcore/clock.go b/vendor/go.uber.org/zap/zapcore/clock.go
index d2ea95b39..422fd82a6 100644
--- a/vendor/go.uber.org/zap/zapcore/clock.go
+++ b/vendor/go.uber.org/zap/zapcore/clock.go
@@ -20,9 +20,7 @@
 
 package zapcore
 
-import (
-	"time"
-)
+import "time"
 
 // DefaultClock is the default clock used by Zap in operations that require
 // time. This clock uses the system clock for all operations.
diff --git a/vendor/go.uber.org/zap/zapcore/console_encoder.go b/vendor/go.uber.org/zap/zapcore/console_encoder.go
index 2307af404..1aa5dc364 100644
--- a/vendor/go.uber.org/zap/zapcore/console_encoder.go
+++ b/vendor/go.uber.org/zap/zapcore/console_encoder.go
@@ -125,11 +125,7 @@ func (c consoleEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer,
 		line.AppendString(ent.Stack)
 	}
 
-	if c.LineEnding != "" {
-		line.AppendString(c.LineEnding)
-	} else {
-		line.AppendString(DefaultLineEnding)
-	}
+	line.AppendString(c.LineEnding)
 	return line, nil
 }
 
diff --git a/vendor/go.uber.org/zap/zapcore/core.go b/vendor/go.uber.org/zap/zapcore/core.go
index a1ef8b034..9dfd64051 100644
--- a/vendor/go.uber.org/zap/zapcore/core.go
+++ b/vendor/go.uber.org/zap/zapcore/core.go
@@ -69,6 +69,15 @@ type ioCore struct {
 	out WriteSyncer
 }
 
+var (
+	_ Core           = (*ioCore)(nil)
+	_ leveledEnabler = (*ioCore)(nil)
+)
+
+func (c *ioCore) Level() Level {
+	return LevelOf(c.LevelEnabler)
+}
+
 func (c *ioCore) With(fields []Field) Core {
 	clone := c.clone()
 	addFields(clone.enc, fields)
diff --git a/vendor/go.uber.org/zap/zapcore/encoder.go b/vendor/go.uber.org/zap/zapcore/encoder.go
index 6601ca166..5769ff3e4 100644
--- a/vendor/go.uber.org/zap/zapcore/encoder.go
+++ b/vendor/go.uber.org/zap/zapcore/encoder.go
@@ -22,6 +22,7 @@ package zapcore
 
 import (
 	"encoding/json"
+	"io"
 	"time"
 
 	"go.uber.org/zap/buffer"
@@ -187,10 +188,13 @@ func (e *TimeEncoder) UnmarshalText(text []byte) error {
 
 // UnmarshalYAML unmarshals YAML to a TimeEncoder.
 // If value is an object with a "layout" field, it will be unmarshaled to  TimeEncoder with given layout.
-//     timeEncoder:
-//       layout: 06/01/02 03:04pm
+//
+//	timeEncoder:
+//	  layout: 06/01/02 03:04pm
+//
 // If value is string, it uses UnmarshalText.
-//     timeEncoder: iso8601
+//
+//	timeEncoder: iso8601
 func (e *TimeEncoder) UnmarshalYAML(unmarshal func(interface{}) error) error {
 	var o struct {
 		Layout string `json:"layout" yaml:"layout"`
@@ -312,14 +316,15 @@ func (e *NameEncoder) UnmarshalText(text []byte) error {
 type EncoderConfig struct {
 	// Set the keys used for each log entry. If any key is empty, that portion
 	// of the entry is omitted.
-	MessageKey    string `json:"messageKey" yaml:"messageKey"`
-	LevelKey      string `json:"levelKey" yaml:"levelKey"`
-	TimeKey       string `json:"timeKey" yaml:"timeKey"`
-	NameKey       string `json:"nameKey" yaml:"nameKey"`
-	CallerKey     string `json:"callerKey" yaml:"callerKey"`
-	FunctionKey   string `json:"functionKey" yaml:"functionKey"`
-	StacktraceKey string `json:"stacktraceKey" yaml:"stacktraceKey"`
-	LineEnding    string `json:"lineEnding" yaml:"lineEnding"`
+	MessageKey     string `json:"messageKey" yaml:"messageKey"`
+	LevelKey       string `json:"levelKey" yaml:"levelKey"`
+	TimeKey        string `json:"timeKey" yaml:"timeKey"`
+	NameKey        string `json:"nameKey" yaml:"nameKey"`
+	CallerKey      string `json:"callerKey" yaml:"callerKey"`
+	FunctionKey    string `json:"functionKey" yaml:"functionKey"`
+	StacktraceKey  string `json:"stacktraceKey" yaml:"stacktraceKey"`
+	SkipLineEnding bool   `json:"skipLineEnding" yaml:"skipLineEnding"`
+	LineEnding     string `json:"lineEnding" yaml:"lineEnding"`
 	// Configure the primitive representations of common complex types. For
 	// example, some users may want all time.Times serialized as floating-point
 	// seconds since epoch, while others may prefer ISO8601 strings.
@@ -330,6 +335,9 @@ type EncoderConfig struct {
 	// Unlike the other primitive type encoders, EncodeName is optional. The
 	// zero value falls back to FullNameEncoder.
 	EncodeName NameEncoder `json:"nameEncoder" yaml:"nameEncoder"`
+	// Configure the encoder for interface{} type objects.
+	// If not provided, objects are encoded using json.Encoder
+	NewReflectedEncoder func(io.Writer) ReflectedEncoder `json:"-" yaml:"-"`
 	// Configures the field separator used by the console encoder. Defaults
 	// to tab.
 	ConsoleSeparator string `json:"consoleSeparator" yaml:"consoleSeparator"`
diff --git a/vendor/go.uber.org/zap/zapcore/entry.go b/vendor/go.uber.org/zap/zapcore/entry.go
index 0885505b7..9d326e95e 100644
--- a/vendor/go.uber.org/zap/zapcore/entry.go
+++ b/vendor/go.uber.org/zap/zapcore/entry.go
@@ -27,10 +27,9 @@ import (
 	"sync"
 	"time"
 
+	"go.uber.org/multierr"
 	"go.uber.org/zap/internal/bufferpool"
 	"go.uber.org/zap/internal/exit"
-
-	"go.uber.org/multierr"
 )
 
 var (
@@ -152,6 +151,27 @@ type Entry struct {
 	Stack      string
 }
 
+// CheckWriteHook is a custom action that may be executed after an entry is
+// written.
+//
+// Register one on a CheckedEntry with the After method.
+//
+//	if ce := logger.Check(...); ce != nil {
+//	  ce = ce.After(hook)
+//	  ce.Write(...)
+//	}
+//
+// You can configure the hook for Fatal log statements at the logger level with
+// the zap.WithFatalHook option.
+type CheckWriteHook interface {
+	// OnWrite is invoked with the CheckedEntry that was written and a list
+	// of fields added with that entry.
+	//
+	// The list of fields DOES NOT include fields that were already added
+	// to the logger with the With method.
+	OnWrite(*CheckedEntry, []Field)
+}
+
 // CheckWriteAction indicates what action to take after a log entry is
 // processed. Actions are ordered in increasing severity.
 type CheckWriteAction uint8
@@ -164,21 +184,36 @@ const (
 	WriteThenGoexit
 	// WriteThenPanic causes a panic after Write.
 	WriteThenPanic
-	// WriteThenFatal causes a fatal os.Exit after Write.
+	// WriteThenFatal causes an os.Exit(1) after Write.
 	WriteThenFatal
 )
 
+// OnWrite implements the OnWrite method to keep CheckWriteAction compatible
+// with the new CheckWriteHook interface which deprecates CheckWriteAction.
+func (a CheckWriteAction) OnWrite(ce *CheckedEntry, _ []Field) {
+	switch a {
+	case WriteThenGoexit:
+		runtime.Goexit()
+	case WriteThenPanic:
+		panic(ce.Message)
+	case WriteThenFatal:
+		exit.With(1)
+	}
+}
+
+var _ CheckWriteHook = CheckWriteAction(0)
+
 // CheckedEntry is an Entry together with a collection of Cores that have
 // already agreed to log it.
 //
-// CheckedEntry references should be created by calling AddCore or Should on a
+// CheckedEntry references should be created by calling AddCore or After on a
 // nil *CheckedEntry. References are returned to a pool after Write, and MUST
 // NOT be retained after calling their Write method.
 type CheckedEntry struct {
 	Entry
 	ErrorOutput WriteSyncer
 	dirty       bool // best-effort detection of pool misuse
-	should      CheckWriteAction
+	after       CheckWriteHook
 	cores       []Core
 }
 
@@ -186,7 +221,7 @@ func (ce *CheckedEntry) reset() {
 	ce.Entry = Entry{}
 	ce.ErrorOutput = nil
 	ce.dirty = false
-	ce.should = WriteThenNoop
+	ce.after = nil
 	for i := range ce.cores {
 		// don't keep references to cores
 		ce.cores[i] = nil
@@ -224,17 +259,11 @@ func (ce *CheckedEntry) Write(fields ...Field) {
 		ce.ErrorOutput.Sync()
 	}
 
-	should, msg := ce.should, ce.Message
-	putCheckedEntry(ce)
-
-	switch should {
-	case WriteThenPanic:
-		panic(msg)
-	case WriteThenFatal:
-		exit.Exit()
-	case WriteThenGoexit:
-		runtime.Goexit()
+	hook := ce.after
+	if hook != nil {
+		hook.OnWrite(ce, fields)
 	}
+	putCheckedEntry(ce)
 }
 
 // AddCore adds a Core that has agreed to log this CheckedEntry. It's intended to be
@@ -252,11 +281,20 @@ func (ce *CheckedEntry) AddCore(ent Entry, core Core) *CheckedEntry {
 // Should sets this CheckedEntry's CheckWriteAction, which controls whether a
 // Core will panic or fatal after writing this log entry. Like AddCore, it's
 // safe to call on nil CheckedEntry references.
+//
+// Deprecated: Use [CheckedEntry.After] instead.
 func (ce *CheckedEntry) Should(ent Entry, should CheckWriteAction) *CheckedEntry {
+	return ce.After(ent, should)
+}
+
+// After sets this CheckEntry's CheckWriteHook, which will be called after this
+// log entry has been written. It's safe to call this on nil CheckedEntry
+// references.
+func (ce *CheckedEntry) After(ent Entry, hook CheckWriteHook) *CheckedEntry {
 	if ce == nil {
 		ce = getCheckedEntry()
 		ce.Entry = ent
 	}
-	ce.should = should
+	ce.after = hook
 	return ce
 }
diff --git a/vendor/go.uber.org/zap/zapcore/error.go b/vendor/go.uber.org/zap/zapcore/error.go
index 74919b0cc..06359907a 100644
--- a/vendor/go.uber.org/zap/zapcore/error.go
+++ b/vendor/go.uber.org/zap/zapcore/error.go
@@ -36,13 +36,13 @@ import (
 // causer (from github.com/pkg/errors), a ${key}Causes field is added with an
 // array of objects containing the errors this error was comprised of.
 //
-//  {
-//    "error": err.Error(),
-//    "errorVerbose": fmt.Sprintf("%+v", err),
-//    "errorCauses": [
-//      ...
-//    ],
-//  }
+//	{
+//	  "error": err.Error(),
+//	  "errorVerbose": fmt.Sprintf("%+v", err),
+//	  "errorCauses": [
+//	    ...
+//	  ],
+//	}
 func encodeError(key string, err error, enc ObjectEncoder) (retErr error) {
 	// Try to capture panics (from nil references or otherwise) when calling
 	// the Error() method
diff --git a/vendor/go.uber.org/zap/zapcore/hook.go b/vendor/go.uber.org/zap/zapcore/hook.go
index 5db4afb30..198def991 100644
--- a/vendor/go.uber.org/zap/zapcore/hook.go
+++ b/vendor/go.uber.org/zap/zapcore/hook.go
@@ -27,6 +27,11 @@ type hooked struct {
 	funcs []func(Entry) error
 }
 
+var (
+	_ Core           = (*hooked)(nil)
+	_ leveledEnabler = (*hooked)(nil)
+)
+
 // RegisterHooks wraps a Core and runs a collection of user-defined callback
 // hooks each time a message is logged. Execution of the callbacks is blocking.
 //
@@ -40,6 +45,10 @@ func RegisterHooks(core Core, hooks ...func(Entry) error) Core {
 	}
 }
 
+func (h *hooked) Level() Level {
+	return LevelOf(h.Core)
+}
+
 func (h *hooked) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
 	// Let the wrapped Core decide whether to log this message or not. This
 	// also gives the downstream a chance to register itself directly with the
diff --git a/vendor/go.uber.org/zap/zapcore/increase_level.go b/vendor/go.uber.org/zap/zapcore/increase_level.go
index 5a1749261..7a11237ae 100644
--- a/vendor/go.uber.org/zap/zapcore/increase_level.go
+++ b/vendor/go.uber.org/zap/zapcore/increase_level.go
@@ -27,6 +27,11 @@ type levelFilterCore struct {
 	level LevelEnabler
 }
 
+var (
+	_ Core           = (*levelFilterCore)(nil)
+	_ leveledEnabler = (*levelFilterCore)(nil)
+)
+
 // NewIncreaseLevelCore creates a core that can be used to increase the level of
 // an existing Core. It cannot be used to decrease the logging level, as it acts
 // as a filter before calling the underlying core. If level decreases the log level,
@@ -45,6 +50,10 @@ func (c *levelFilterCore) Enabled(lvl Level) bool {
 	return c.level.Enabled(lvl)
 }
 
+func (c *levelFilterCore) Level() Level {
+	return LevelOf(c.level)
+}
+
 func (c *levelFilterCore) With(fields []Field) Core {
 	return &levelFilterCore{c.core.With(fields), c.level}
 }
diff --git a/vendor/go.uber.org/zap/zapcore/json_encoder.go b/vendor/go.uber.org/zap/zapcore/json_encoder.go
index af220d9b4..3921c5cd3 100644
--- a/vendor/go.uber.org/zap/zapcore/json_encoder.go
+++ b/vendor/go.uber.org/zap/zapcore/json_encoder.go
@@ -22,7 +22,6 @@ package zapcore
 
 import (
 	"encoding/base64"
-	"encoding/json"
 	"math"
 	"sync"
 	"time"
@@ -64,7 +63,7 @@ type jsonEncoder struct {
 
 	// for encoding generic values by reflection
 	reflectBuf *buffer.Buffer
-	reflectEnc *json.Encoder
+	reflectEnc ReflectedEncoder
 }
 
 // NewJSONEncoder creates a fast, low-allocation JSON encoder. The encoder
@@ -72,7 +71,9 @@ type jsonEncoder struct {
 //
 // Note that the encoder doesn't deduplicate keys, so it's possible to produce
 // a message like
-//   {"foo":"bar","foo":"baz"}
+//
+//	{"foo":"bar","foo":"baz"}
+//
 // This is permitted by the JSON specification, but not encouraged. Many
 // libraries will ignore duplicate key-value pairs (typically keeping the last
 // pair) when unmarshaling, but users should attempt to avoid adding duplicate
@@ -82,6 +83,17 @@ func NewJSONEncoder(cfg EncoderConfig) Encoder {
 }
 
 func newJSONEncoder(cfg EncoderConfig, spaced bool) *jsonEncoder {
+	if cfg.SkipLineEnding {
+		cfg.LineEnding = ""
+	} else if cfg.LineEnding == "" {
+		cfg.LineEnding = DefaultLineEnding
+	}
+
+	// If no EncoderConfig.NewReflectedEncoder is provided by the user, then use default
+	if cfg.NewReflectedEncoder == nil {
+		cfg.NewReflectedEncoder = defaultReflectedEncoder
+	}
+
 	return &jsonEncoder{
 		EncoderConfig: &cfg,
 		buf:           bufferpool.Get(),
@@ -118,6 +130,11 @@ func (enc *jsonEncoder) AddComplex128(key string, val complex128) {
 	enc.AppendComplex128(val)
 }
 
+func (enc *jsonEncoder) AddComplex64(key string, val complex64) {
+	enc.addKey(key)
+	enc.AppendComplex64(val)
+}
+
 func (enc *jsonEncoder) AddDuration(key string, val time.Duration) {
 	enc.addKey(key)
 	enc.AppendDuration(val)
@@ -141,10 +158,7 @@ func (enc *jsonEncoder) AddInt64(key string, val int64) {
 func (enc *jsonEncoder) resetReflectBuf() {
 	if enc.reflectBuf == nil {
 		enc.reflectBuf = bufferpool.Get()
-		enc.reflectEnc = json.NewEncoder(enc.reflectBuf)
-
-		// For consistency with our custom JSON encoder.
-		enc.reflectEnc.SetEscapeHTML(false)
+		enc.reflectEnc = enc.NewReflectedEncoder(enc.reflectBuf)
 	} else {
 		enc.reflectBuf.Reset()
 	}
@@ -206,10 +220,16 @@ func (enc *jsonEncoder) AppendArray(arr ArrayMarshaler) error {
 }
 
 func (enc *jsonEncoder) AppendObject(obj ObjectMarshaler) error {
+	// Close ONLY new openNamespaces that are created during
+	// AppendObject().
+	old := enc.openNamespaces
+	enc.openNamespaces = 0
 	enc.addElementSeparator()
 	enc.buf.AppendByte('{')
 	err := obj.MarshalLogObject(enc)
 	enc.buf.AppendByte('}')
+	enc.closeOpenNamespaces()
+	enc.openNamespaces = old
 	return err
 }
 
@@ -225,20 +245,23 @@ func (enc *jsonEncoder) AppendByteString(val []byte) {
 	enc.buf.AppendByte('"')
 }
 
-func (enc *jsonEncoder) AppendComplex128(val complex128) {
+// appendComplex appends the encoded form of the provided complex128 value.
+// precision specifies the encoding precision for the real and imaginary
+// components of the complex number.
+func (enc *jsonEncoder) appendComplex(val complex128, precision int) {
 	enc.addElementSeparator()
 	// Cast to a platform-independent, fixed-size type.
 	r, i := float64(real(val)), float64(imag(val))
 	enc.buf.AppendByte('"')
 	// Because we're always in a quoted string, we can use strconv without
 	// special-casing NaN and +/-Inf.
-	enc.buf.AppendFloat(r, 64)
+	enc.buf.AppendFloat(r, precision)
 	// If imaginary part is less than 0, minus (-) sign is added by default
 	// by AppendFloat.
 	if i >= 0 {
 		enc.buf.AppendByte('+')
 	}
-	enc.buf.AppendFloat(i, 64)
+	enc.buf.AppendFloat(i, precision)
 	enc.buf.AppendByte('i')
 	enc.buf.AppendByte('"')
 }
@@ -301,28 +324,28 @@ func (enc *jsonEncoder) AppendUint64(val uint64) {
 	enc.buf.AppendUint(val)
 }
 
-func (enc *jsonEncoder) AddComplex64(k string, v complex64) { enc.AddComplex128(k, complex128(v)) }
-func (enc *jsonEncoder) AddInt(k string, v int)             { enc.AddInt64(k, int64(v)) }
-func (enc *jsonEncoder) AddInt32(k string, v int32)         { enc.AddInt64(k, int64(v)) }
-func (enc *jsonEncoder) AddInt16(k string, v int16)         { enc.AddInt64(k, int64(v)) }
-func (enc *jsonEncoder) AddInt8(k string, v int8)           { enc.AddInt64(k, int64(v)) }
-func (enc *jsonEncoder) AddUint(k string, v uint)           { enc.AddUint64(k, uint64(v)) }
-func (enc *jsonEncoder) AddUint32(k string, v uint32)       { enc.AddUint64(k, uint64(v)) }
-func (enc *jsonEncoder) AddUint16(k string, v uint16)       { enc.AddUint64(k, uint64(v)) }
-func (enc *jsonEncoder) AddUint8(k string, v uint8)         { enc.AddUint64(k, uint64(v)) }
-func (enc *jsonEncoder) AddUintptr(k string, v uintptr)     { enc.AddUint64(k, uint64(v)) }
-func (enc *jsonEncoder) AppendComplex64(v complex64)        { enc.AppendComplex128(complex128(v)) }
-func (enc *jsonEncoder) AppendFloat64(v float64)            { enc.appendFloat(v, 64) }
-func (enc *jsonEncoder) AppendFloat32(v float32)            { enc.appendFloat(float64(v), 32) }
-func (enc *jsonEncoder) AppendInt(v int)                    { enc.AppendInt64(int64(v)) }
-func (enc *jsonEncoder) AppendInt32(v int32)                { enc.AppendInt64(int64(v)) }
-func (enc *jsonEncoder) AppendInt16(v int16)                { enc.AppendInt64(int64(v)) }
-func (enc *jsonEncoder) AppendInt8(v int8)                  { enc.AppendInt64(int64(v)) }
-func (enc *jsonEncoder) AppendUint(v uint)                  { enc.AppendUint64(uint64(v)) }
-func (enc *jsonEncoder) AppendUint32(v uint32)              { enc.AppendUint64(uint64(v)) }
-func (enc *jsonEncoder) AppendUint16(v uint16)              { enc.AppendUint64(uint64(v)) }
-func (enc *jsonEncoder) AppendUint8(v uint8)                { enc.AppendUint64(uint64(v)) }
-func (enc *jsonEncoder) AppendUintptr(v uintptr)            { enc.AppendUint64(uint64(v)) }
+func (enc *jsonEncoder) AddInt(k string, v int)         { enc.AddInt64(k, int64(v)) }
+func (enc *jsonEncoder) AddInt32(k string, v int32)     { enc.AddInt64(k, int64(v)) }
+func (enc *jsonEncoder) AddInt16(k string, v int16)     { enc.AddInt64(k, int64(v)) }
+func (enc *jsonEncoder) AddInt8(k string, v int8)       { enc.AddInt64(k, int64(v)) }
+func (enc *jsonEncoder) AddUint(k string, v uint)       { enc.AddUint64(k, uint64(v)) }
+func (enc *jsonEncoder) AddUint32(k string, v uint32)   { enc.AddUint64(k, uint64(v)) }
+func (enc *jsonEncoder) AddUint16(k string, v uint16)   { enc.AddUint64(k, uint64(v)) }
+func (enc *jsonEncoder) AddUint8(k string, v uint8)     { enc.AddUint64(k, uint64(v)) }
+func (enc *jsonEncoder) AddUintptr(k string, v uintptr) { enc.AddUint64(k, uint64(v)) }
+func (enc *jsonEncoder) AppendComplex64(v complex64)    { enc.appendComplex(complex128(v), 32) }
+func (enc *jsonEncoder) AppendComplex128(v complex128)  { enc.appendComplex(complex128(v), 64) }
+func (enc *jsonEncoder) AppendFloat64(v float64)        { enc.appendFloat(v, 64) }
+func (enc *jsonEncoder) AppendFloat32(v float32)        { enc.appendFloat(float64(v), 32) }
+func (enc *jsonEncoder) AppendInt(v int)                { enc.AppendInt64(int64(v)) }
+func (enc *jsonEncoder) AppendInt32(v int32)            { enc.AppendInt64(int64(v)) }
+func (enc *jsonEncoder) AppendInt16(v int16)            { enc.AppendInt64(int64(v)) }
+func (enc *jsonEncoder) AppendInt8(v int8)              { enc.AppendInt64(int64(v)) }
+func (enc *jsonEncoder) AppendUint(v uint)              { enc.AppendUint64(uint64(v)) }
+func (enc *jsonEncoder) AppendUint32(v uint32)          { enc.AppendUint64(uint64(v)) }
+func (enc *jsonEncoder) AppendUint16(v uint16)          { enc.AppendUint64(uint64(v)) }
+func (enc *jsonEncoder) AppendUint8(v uint8)            { enc.AppendUint64(uint64(v)) }
+func (enc *jsonEncoder) AppendUintptr(v uintptr)        { enc.AppendUint64(uint64(v)) }
 
 func (enc *jsonEncoder) Clone() Encoder {
 	clone := enc.clone()
@@ -343,7 +366,7 @@ func (enc *jsonEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer,
 	final := enc.clone()
 	final.buf.AppendByte('{')
 
-	if final.LevelKey != "" {
+	if final.LevelKey != "" && final.EncodeLevel != nil {
 		final.addKey(final.LevelKey)
 		cur := final.buf.Len()
 		final.EncodeLevel(ent.Level, final)
@@ -404,11 +427,7 @@ func (enc *jsonEncoder) EncodeEntry(ent Entry, fields []Field) (*buffer.Buffer,
 		final.AddString(final.StacktraceKey, ent.Stack)
 	}
 	final.buf.AppendByte('}')
-	if final.LineEnding != "" {
-		final.buf.AppendString(final.LineEnding)
-	} else {
-		final.buf.AppendString(DefaultLineEnding)
-	}
+	final.buf.AppendString(final.LineEnding)
 
 	ret := final.buf
 	putJSONEncoder(final)
@@ -423,6 +442,7 @@ func (enc *jsonEncoder) closeOpenNamespaces() {
 	for i := 0; i < enc.openNamespaces; i++ {
 		enc.buf.AppendByte('}')
 	}
+	enc.openNamespaces = 0
 }
 
 func (enc *jsonEncoder) addKey(key string) {
diff --git a/vendor/go.uber.org/zap/zapcore/level.go b/vendor/go.uber.org/zap/zapcore/level.go
index e575c9f43..e01a24131 100644
--- a/vendor/go.uber.org/zap/zapcore/level.go
+++ b/vendor/go.uber.org/zap/zapcore/level.go
@@ -53,8 +53,62 @@ const (
 
 	_minLevel = DebugLevel
 	_maxLevel = FatalLevel
+
+	// InvalidLevel is an invalid value for Level.
+	//
+	// Core implementations may panic if they see messages of this level.
+	InvalidLevel = _maxLevel + 1
 )
 
+// ParseLevel parses a level based on the lower-case or all-caps ASCII
+// representation of the log level. If the provided ASCII representation is
+// invalid an error is returned.
+//
+// This is particularly useful when dealing with text input to configure log
+// levels.
+func ParseLevel(text string) (Level, error) {
+	var level Level
+	err := level.UnmarshalText([]byte(text))
+	return level, err
+}
+
+type leveledEnabler interface {
+	LevelEnabler
+
+	Level() Level
+}
+
+// LevelOf reports the minimum enabled log level for the given LevelEnabler
+// from Zap's supported log levels, or [InvalidLevel] if none of them are
+// enabled.
+//
+// A LevelEnabler may implement a 'Level() Level' method to override the
+// behavior of this function.
+//
+//	func (c *core) Level() Level {
+//		return c.currentLevel
+//	}
+//
+// It is recommended that [Core] implementations that wrap other cores use
+// LevelOf to retrieve the level of the wrapped core. For example,
+//
+//	func (c *coreWrapper) Level() Level {
+//		return zapcore.LevelOf(c.wrappedCore)
+//	}
+func LevelOf(enab LevelEnabler) Level {
+	if lvler, ok := enab.(leveledEnabler); ok {
+		return lvler.Level()
+	}
+
+	for lvl := _minLevel; lvl <= _maxLevel; lvl++ {
+		if enab.Enabled(lvl) {
+			return lvl
+		}
+	}
+
+	return InvalidLevel
+}
+
 // String returns a lower-case ASCII representation of the log level.
 func (l Level) String() string {
 	switch l {
diff --git a/vendor/go.uber.org/zap/global_prego112.go b/vendor/go.uber.org/zap/zapcore/reflected_encoder.go
similarity index 64%
rename from vendor/go.uber.org/zap/global_prego112.go
rename to vendor/go.uber.org/zap/zapcore/reflected_encoder.go
index d3ab9af93..8746360ec 100644
--- a/vendor/go.uber.org/zap/global_prego112.go
+++ b/vendor/go.uber.org/zap/zapcore/reflected_encoder.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2019 Uber Technologies, Inc.
+// 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
@@ -18,9 +18,24 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 // THE SOFTWARE.
 
-// See #682 for more information.
-// +build !go1.12
+package zapcore
 
-package zap
+import (
+	"encoding/json"
+	"io"
+)
 
-const _stdLogDefaultDepth = 2
+// ReflectedEncoder serializes log fields that can't be serialized with Zap's
+// JSON encoder. These have the ReflectType field type.
+// Use EncoderConfig.NewReflectedEncoder to set this.
+type ReflectedEncoder interface {
+	// Encode encodes and writes to the underlying data stream.
+	Encode(interface{}) error
+}
+
+func defaultReflectedEncoder(w io.Writer) ReflectedEncoder {
+	enc := json.NewEncoder(w)
+	// For consistency with our custom JSON encoder.
+	enc.SetEscapeHTML(false)
+	return enc
+}
diff --git a/vendor/go.uber.org/zap/zapcore/sampler.go b/vendor/go.uber.org/zap/zapcore/sampler.go
index 31ed96e12..dc518055a 100644
--- a/vendor/go.uber.org/zap/zapcore/sampler.go
+++ b/vendor/go.uber.org/zap/zapcore/sampler.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
+// Copyright (c) 2016-2022 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
@@ -113,12 +113,12 @@ func nopSamplingHook(Entry, SamplingDecision) {}
 // This hook may be used to get visibility into the performance of the sampler.
 // For example, use it to track metrics of dropped versus sampled logs.
 //
-//  var dropped atomic.Int64
-//  zapcore.SamplerHook(func(ent zapcore.Entry, dec zapcore.SamplingDecision) {
-//    if dec&zapcore.LogDropped > 0 {
-//      dropped.Inc()
-//    }
-//  })
+//	var dropped atomic.Int64
+//	zapcore.SamplerHook(func(ent zapcore.Entry, dec zapcore.SamplingDecision) {
+//	  if dec&zapcore.LogDropped > 0 {
+//	    dropped.Inc()
+//	  }
+//	})
 func SamplerHook(hook func(entry Entry, dec SamplingDecision)) SamplerOption {
 	return optionFunc(func(s *sampler) {
 		s.hook = hook
@@ -133,10 +133,21 @@ func SamplerHook(hook func(entry Entry, dec SamplingDecision)) SamplerOption {
 // each tick. If more Entries with the same level and message are seen during
 // the same interval, every Mth message is logged and the rest are dropped.
 //
+// For example,
+//
+//	core = NewSamplerWithOptions(core, time.Second, 10, 5)
+//
+// This will log the first 10 log entries with the same level and message
+// in a one second interval as-is. Following that, it will allow through
+// every 5th log entry with the same level and message in that interval.
+//
+// If thereafter is zero, the Core will drop all log entries after the first N
+// in that interval.
+//
 // Sampler can be configured to report sampling decisions with the SamplerHook
 // option.
 //
-// Keep in mind that zap's sampling implementation is optimized for speed over
+// Keep in mind that Zap's sampling implementation is optimized for speed over
 // absolute precision; under load, each tick may be slightly over- or
 // under-sampled.
 func NewSamplerWithOptions(core Core, tick time.Duration, first, thereafter int, opts ...SamplerOption) Core {
@@ -164,6 +175,11 @@ type sampler struct {
 	hook              func(Entry, SamplingDecision)
 }
 
+var (
+	_ Core           = (*sampler)(nil)
+	_ leveledEnabler = (*sampler)(nil)
+)
+
 // NewSampler creates a Core that samples incoming entries, which
 // caps the CPU and I/O load of logging while attempting to preserve a
 // representative subset of your logs.
@@ -181,6 +197,10 @@ func NewSampler(core Core, tick time.Duration, first, thereafter int) Core {
 	return NewSamplerWithOptions(core, tick, first, thereafter)
 }
 
+func (s *sampler) Level() Level {
+	return LevelOf(s.Core)
+}
+
 func (s *sampler) With(fields []Field) Core {
 	return &sampler{
 		Core:       s.Core.With(fields),
@@ -200,7 +220,7 @@ func (s *sampler) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
 	if ent.Level >= _minLevel && ent.Level <= _maxLevel {
 		counter := s.counts.get(ent.Level, ent.Message)
 		n := counter.IncCheckReset(ent.Time, s.tick)
-		if n > s.first && (n-s.first)%s.thereafter != 0 {
+		if n > s.first && (s.thereafter == 0 || (n-s.first)%s.thereafter != 0) {
 			s.hook(ent, LogDropped)
 			return ce
 		}
diff --git a/vendor/go.uber.org/zap/zapcore/tee.go b/vendor/go.uber.org/zap/zapcore/tee.go
index 07a32eef9..9bb32f055 100644
--- a/vendor/go.uber.org/zap/zapcore/tee.go
+++ b/vendor/go.uber.org/zap/zapcore/tee.go
@@ -1,4 +1,4 @@
-// Copyright (c) 2016 Uber Technologies, Inc.
+// Copyright (c) 2016-2022 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
@@ -24,6 +24,11 @@ import "go.uber.org/multierr"
 
 type multiCore []Core
 
+var (
+	_ leveledEnabler = multiCore(nil)
+	_ Core           = multiCore(nil)
+)
+
 // NewTee creates a Core that duplicates log entries into two or more
 // underlying Cores.
 //
@@ -48,6 +53,16 @@ func (mc multiCore) With(fields []Field) Core {
 	return clone
 }
 
+func (mc multiCore) Level() Level {
+	minLvl := _maxLevel // mc is never empty
+	for i := range mc {
+		if lvl := LevelOf(mc[i]); lvl < minLvl {
+			minLvl = lvl
+		}
+	}
+	return minLvl
+}
+
 func (mc multiCore) Enabled(lvl Level) bool {
 	for i := range mc {
 		if mc[i].Enabled(lvl) {
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 950d93996..ed9ac55b1 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -29,6 +29,9 @@ contrib.go.opencensus.io/exporter/prometheus
 # contrib.go.opencensus.io/exporter/zipkin v0.1.2
 ## explicit
 contrib.go.opencensus.io/exporter/zipkin
+# github.com/benbjohnson/clock v1.1.0
+## explicit; go 1.15
+github.com/benbjohnson/clock
 # github.com/beorn7/perks v1.0.1
 ## explicit; go 1.11
 github.com/beorn7/perks/quantile
@@ -175,7 +178,7 @@ github.com/googleapis/gax-go/v2
 github.com/googleapis/gax-go/v2/apierror
 github.com/googleapis/gax-go/v2/apierror/internal/proto
 github.com/googleapis/gax-go/v2/internal
-# github.com/gorilla/websocket v1.4.2
+# github.com/gorilla/websocket v1.5.0
 ## explicit; go 1.12
 github.com/gorilla/websocket
 # github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3
@@ -299,10 +302,11 @@ go.uber.org/automaxprocs/maxprocs
 # go.uber.org/multierr v1.6.0
 ## explicit; go 1.12
 go.uber.org/multierr
-# go.uber.org/zap v1.19.1
-## explicit; go 1.13
+# go.uber.org/zap v1.24.0
+## explicit; go 1.19
 go.uber.org/zap
 go.uber.org/zap/buffer
+go.uber.org/zap/internal
 go.uber.org/zap/internal/bufferpool
 go.uber.org/zap/internal/color
 go.uber.org/zap/internal/exit


Test patch:
diff --git a/.github/workflows/knative-go-test.yaml b/.github/workflows/knative-go-test.yaml
index 52a2d60ed..75d921e21 100644
--- a/.github/workflows/knative-go-test.yaml
+++ b/.github/workflows/knative-go-test.yaml
@@ -1,7 +1,7 @@
 # Copyright 2022 The Knative Authors.
 # SPDX-License-Identifier: Apache-2.0
 
-# This file is automagically synced here from github.com/knative-sandbox/knobots
+# This file is automagically synced here from github.com/knative-extensions/knobots
 
 name: Test
 
diff --git a/apis/duck/cached_test.go b/apis/duck/cached_test.go
index 9ab0369f9..656425129 100644
--- a/apis/duck/cached_test.go
+++ b/apis/duck/cached_test.go
@@ -19,10 +19,10 @@ package duck
 import (
 	"context"
 	"fmt"
+	"sync/atomic"
 	"testing"
 	"time"
 
-	"go.uber.org/atomic"
 	"golang.org/x/sync/errgroup"
 
 	"k8s.io/apimachinery/pkg/runtime/schema"
@@ -37,7 +37,7 @@ type BlockingInformerFactory struct {
 var _ InformerFactory = (*BlockingInformerFactory)(nil)
 
 func (bif *BlockingInformerFactory) Get(ctx context.Context, gvr schema.GroupVersionResource) (cache.SharedIndexInformer, cache.GenericLister, error) {
-	bif.nCalls.Inc()
+	bif.nCalls.Add(1)
 	// Wait here until we can acquire the lock
 	<-bif.block
 
@@ -58,7 +58,7 @@ func TestSameGVR(t *testing.T) {
 	}
 
 	// counts the number of calls to cif.Get that returned
-	retGetCount := atomic.NewInt32(0)
+	var retGetCount atomic.Int32
 
 	errGrp, ctx := errgroup.WithContext(context.Background())
 
@@ -75,7 +75,7 @@ func TestSameGVR(t *testing.T) {
 	for i := 0; i < iter; i++ {
 		errGrp.Go(func() error {
 			_, _, err := cif.Get(ctx, gvr)
-			retGetCount.Inc()
+			retGetCount.Add(1)
 			return err
 		})
 	}
@@ -119,7 +119,7 @@ func TestDifferentGVRs(t *testing.T) {
 	}
 
 	// counts the number of calls to cif.Get that returned
-	retGetCount := atomic.NewInt32(0)
+	var retGetCount atomic.Int32
 
 	errGrp, ctx := errgroup.WithContext(context.Background())
 
@@ -136,7 +136,7 @@ func TestDifferentGVRs(t *testing.T) {
 
 		errGrp.Go(func() error {
 			_, _, err := cif.Get(ctx, gvr)
-			retGetCount.Inc()
+			retGetCount.Add(1)
 			return err
 		})
 	}
diff --git a/controller/controller_test.go b/controller/controller_test.go
index e75be6469..e6920d5d5 100644
--- a/controller/controller_test.go
+++ b/controller/controller_test.go
@@ -21,11 +21,11 @@ import (
 	"errors"
 	"fmt"
 	"sync"
+	"sync/atomic"
 	"testing"
 	"time"
 
 	"github.com/google/go-cmp/cmp"
-	"go.uber.org/atomic"
 
 	coordinationv1 "k8s.io/api/coordination/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -874,7 +874,7 @@ type CountingReconciler struct {
 }
 
 func (cr *CountingReconciler) Reconcile(context.Context, string) error {
-	cr.count.Inc()
+	cr.count.Add(1)
 	return nil
 }
 
@@ -927,7 +927,7 @@ type countingLeaderAwareReconciler struct {
 var _ reconciler.LeaderAware = (*countingLeaderAwareReconciler)(nil)
 
 func (cr *countingLeaderAwareReconciler) Promote(b reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error {
-	cr.promotionCount.Inc()
+	cr.promotionCount.Add(1)
 	return cr.LeaderAwareFuncs.Promote(b, enq)
 }
 
@@ -941,7 +941,7 @@ func (cr *countingLeaderAwareReconciler) Reconcile(ctx context.Context, key stri
 		Namespace: namespace,
 		Name:      name,
 	}) {
-		cr.reconcileCount.Inc()
+		cr.reconcileCount.Add(1)
 	}
 	return nil
 }
diff --git a/reconciler/testing/context.go b/reconciler/testing/context.go
index 150c59bf2..0a36caefc 100644
--- a/reconciler/testing/context.go
+++ b/reconciler/testing/context.go
@@ -18,11 +18,10 @@ package testing
 
 import (
 	"context"
+	"sync/atomic"
 	"testing"
 	"time"
 
-	"go.uber.org/atomic"
-
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/runtime/schema"
@@ -94,7 +93,7 @@ func RunAndSyncInformers(ctx context.Context, informers ...controller.Informer)
 
 		c.PrependReactor("list", "*", func(action clientgotesting.Action) (handled bool, ret runtime.Object, err error) {
 			// Every list (before actual informer usage) is going to be followed by a Watch call.
-			watchesPending.Inc()
+			watchesPending.Add(1)
 			return false, nil, nil
 		})
 
@@ -108,7 +107,7 @@ func RunAndSyncInformers(ctx context.Context, informers ...controller.Informer)
 				return false, nil, err
 			}
 
-			watchesPending.Dec()
+			watchesPending.Add(-1)
 
 			return true, watch, nil
 		})
diff --git a/reconciler/testing/hooks.go b/reconciler/testing/hooks.go
index c89be34a0..c4129c612 100644
--- a/reconciler/testing/hooks.go
+++ b/reconciler/testing/hooks.go
@@ -20,9 +20,9 @@ package testing
 import (
 	"errors"
 	"sync"
+	"sync/atomic"
 	"time"
 
-	"go.uber.org/atomic"
 	"k8s.io/apimachinery/pkg/runtime"
 	kubetesting "k8s.io/client-go/testing"
 )
@@ -94,16 +94,18 @@ type Hooks struct {
 // more fake clients and wait for all hooks to complete.
 // TODO(grantr): Allow validating that a hook never fires
 func NewHooks() *Hooks {
+	var ci atomic.Int32
+	ci.Store(-1)
 	return &Hooks{
 		completionCh:    make(chan int32, 100),
-		completionIndex: atomic.NewInt32(-1),
+		completionIndex: &ci,
 	}
 }
 
 // OnCreate attaches a create hook to the given Fake. The hook function is
 // executed every time a resource of the given type is created.
 func (h *Hooks) OnCreate(fake *kubetesting.Fake, resource string, rf CreateHookFunc) {
-	index := h.completionIndex.Inc()
+	index := h.completionIndex.Add(1)
 	fake.PrependReactor("create", resource, func(a kubetesting.Action) (bool, runtime.Object, error) {
 		obj := a.(kubetesting.CreateActionImpl).Object
 
@@ -119,7 +121,7 @@ func (h *Hooks) OnCreate(fake *kubetesting.Fake, resource string, rf CreateHookF
 // OnUpdate attaches an update hook to the given Fake. The hook function is
 // executed every time a resource of the given type is updated.
 func (h *Hooks) OnUpdate(fake *kubetesting.Fake, resource string, rf UpdateHookFunc) {
-	index := h.completionIndex.Inc()
+	index := h.completionIndex.Add(1)
 	fake.PrependReactor("update", resource, func(a kubetesting.Action) (bool, runtime.Object, error) {
 		obj := a.(kubetesting.UpdateActionImpl).Object
 
@@ -135,7 +137,7 @@ func (h *Hooks) OnUpdate(fake *kubetesting.Fake, resource string, rf UpdateHookF
 // OnDelete attaches a delete hook to the given Fake. The hook function is
 // executed every time a resource of the given type is deleted.
 func (h *Hooks) OnDelete(fake *kubetesting.Fake, resource string, rf DeleteHookFunc) {
-	index := h.completionIndex.Inc()
+	index := h.completionIndex.Add(1)
 	fake.PrependReactor("delete", resource, func(a kubetesting.Action) (bool, runtime.Object, error) {
 		name := a.(kubetesting.DeleteActionImpl).Name
 
@@ -173,7 +175,7 @@ func (h *Hooks) WaitForHooks(timeout time.Duration) error {
 		case i := <-h.completionCh:
 			hookCompletions[i] = HookComplete
 			if len(hookCompletions) == ci {
-				h.completionIndex.Dec()
+				h.completionIndex.Add(-1)
 				return nil
 			}
 		case <-timer:
diff --git a/test/spoof/spoof_test.go b/test/spoof/spoof_test.go
index f1da85238..df07f4094 100644
--- a/test/spoof/spoof_test.go
+++ b/test/spoof/spoof_test.go
@@ -24,11 +24,10 @@ import (
 	"fmt"
 	"net/http"
 	"net/url"
+	"sync/atomic"
 	"time"
 
 	"testing"
-
-	"go.uber.org/atomic"
 )
 
 var (
@@ -49,7 +48,7 @@ type fakeTransport struct {
 }
 
 func (ft *fakeTransport) RoundTrip(req *http.Request) (*http.Response, error) {
-	call := ft.calls.Inc()
+	call := ft.calls.Add(1)
 	if ft.response != nil && call == 2 {
 		// If both a response and an error is defined, we return just the response on
 		// the second call to simulate a retry that passes eventually.
@@ -159,7 +158,7 @@ func TestSpoofingClient_WaitForEndpointState(t *testing.T) {
 		inState: func() ResponseChecker {
 			var calls atomic.Int32
 			return func(resp *Response) (done bool, err error) {
-				val := calls.Inc()
+				val := calls.Add(1)
 				// Stop the looping on the third invocation
 				return val == 3, nil
 			}
diff --git a/test/zipkin/util.go b/test/zipkin/util.go
index 72d867f19..2e9b8dbae 100644
--- a/test/zipkin/util.go
+++ b/test/zipkin/util.go
@@ -28,10 +28,10 @@ import (
 	"strconv"
 	"strings"
 	"sync"
+	"sync/atomic"
 	"testing"
 	"time"
 
-	"go.uber.org/atomic"
 	tracingconfig "knative.dev/pkg/tracing/config"
 
 	"github.com/openzipkin/zipkin-go/model"
diff --git a/vendor/go.uber.org/zap/internal/ztest/clock.go b/vendor/go.uber.org/zap/internal/ztest/clock.go
new file mode 100644
index 000000000..fe8026d94
--- /dev/null
+++ b/vendor/go.uber.org/zap/internal/ztest/clock.go
@@ -0,0 +1,50 @@
+// Copyright (c) 2021 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 ztest
+
+import (
+	"time"
+
+	"github.com/benbjohnson/clock"
+)
+
+// MockClock provides control over the time.
+type MockClock struct{ m *clock.Mock }
+
+// NewMockClock builds a new mock clock that provides control of time.
+func NewMockClock() *MockClock {
+	return &MockClock{clock.NewMock()}
+}
+
+// Now reports the current time.
+func (c *MockClock) Now() time.Time {
+	return c.m.Now()
+}
+
+// NewTicker returns a time.Ticker that ticks at the specified frequency.
+func (c *MockClock) NewTicker(d time.Duration) *time.Ticker {
+	return &time.Ticker{C: c.m.Ticker(d).C}
+}
+
+// Add progresses time by the given duration.
+func (c *MockClock) Add(d time.Duration) {
+	c.m.Add(d)
+}
diff --git a/vendor/go.uber.org/zap/internal/ztest/timeout.go b/vendor/go.uber.org/zap/internal/ztest/timeout.go
index f7d58f316..e4222f947 100644
--- a/vendor/go.uber.org/zap/internal/ztest/timeout.go
+++ b/vendor/go.uber.org/zap/internal/ztest/timeout.go
@@ -42,11 +42,11 @@ func Sleep(base time.Duration) {
 // Initialize checks the environment and alters the timeout scale accordingly.
 // It returns a function to undo the scaling.
 func Initialize(factor string) func() {
-	original := _timeoutScale
 	fv, err := strconv.ParseFloat(factor, 64)
 	if err != nil {
 		panic(err)
 	}
+	original := _timeoutScale
 	_timeoutScale = fv
 	return func() { _timeoutScale = original }
 }
diff --git a/vendor/go.uber.org/zap/internal/ztest/writer.go b/vendor/go.uber.org/zap/internal/ztest/writer.go
index 9fdd5805e..f54d8569e 100644
--- a/vendor/go.uber.org/zap/internal/ztest/writer.go
+++ b/vendor/go.uber.org/zap/internal/ztest/writer.go
@@ -23,7 +23,7 @@ package ztest
 import (
 	"bytes"
 	"errors"
-	"io/ioutil"
+	"io"
 	"strings"
 )
 
@@ -50,12 +50,12 @@ func (s *Syncer) Called() bool {
 	return s.called
 }
 
-// A Discarder sends all writes to ioutil.Discard.
+// A Discarder sends all writes to io.Discard.
 type Discarder struct{ Syncer }
 
 // Write implements io.Writer.
 func (d *Discarder) Write(b []byte) (int, error) {
-	return ioutil.Discard.Write(b)
+	return io.Discard.Write(b)
 }
 
 // FailWriter is a WriteSyncer that always returns an error on writes.
diff --git a/vendor/go.uber.org/zap/zaptest/logger.go b/vendor/go.uber.org/zap/zaptest/logger.go
index 1e2451c26..6a4a35497 100644
--- a/vendor/go.uber.org/zap/zaptest/logger.go
+++ b/vendor/go.uber.org/zap/zaptest/logger.go
@@ -61,7 +61,7 @@ func WrapOptions(zapOpts ...zap.Option) LoggerOption {
 // NewLogger builds a new Logger that logs all messages to the given
 // testing.TB.
 //
-//   logger := zaptest.NewLogger(t)
+//	logger := zaptest.NewLogger(t)
 //
 // Use this with a *testing.T or *testing.B to get logs which get printed only
 // if a test fails or if you ran go test -v.
@@ -69,11 +69,11 @@ func WrapOptions(zapOpts ...zap.Option) LoggerOption {
 // The returned logger defaults to logging debug level messages and above.
 // This may be changed by passing a zaptest.Level during construction.
 //
-//   logger := zaptest.NewLogger(t, zaptest.Level(zap.WarnLevel))
+//	logger := zaptest.NewLogger(t, zaptest.Level(zap.WarnLevel))
 //
 // You may also pass zap.Option's to customize test logger.
 //
-//   logger := zaptest.NewLogger(t, zaptest.WrapOptions(zap.AddCaller()))
+//	logger := zaptest.NewLogger(t, zaptest.WrapOptions(zap.AddCaller()))
 func NewLogger(t TestingT, opts ...LoggerOption) *zap.Logger {
 	cfg := loggerOptions{
 		Level: zapcore.DebugLevel,
diff --git a/vendor/go.uber.org/zap/zaptest/writer.go b/vendor/go.uber.org/zap/zaptest/writer.go
index 0701630e1..4b772f8c2 100644
--- a/vendor/go.uber.org/zap/zaptest/writer.go
+++ b/vendor/go.uber.org/zap/zaptest/writer.go
@@ -26,7 +26,7 @@ type (
 	// A Syncer is a spy for the Sync portion of zapcore.WriteSyncer.
 	Syncer = ztest.Syncer
 
-	// A Discarder sends all writes to ioutil.Discard.
+	// A Discarder sends all writes to io.Discard.
 	Discarder = ztest.Discarder
 
 	// FailWriter is a WriteSyncer that always returns an error on writes.