fix: update go.mod (#20071)

Signed-off-by: Shengwen Yu <yshengwen@vmware.com>
This commit is contained in:
Shengwen YU 2024-03-01 13:24:14 +08:00 committed by GitHub
parent c4291d4388
commit c2cb8ea4a0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1001 changed files with 82753 additions and 34801 deletions

View File

@ -15,7 +15,7 @@ require (
github.com/cloudevents/sdk-go/v2 v2.13.0
github.com/coreos/go-oidc/v3 v3.0.0
github.com/dghubble/sling v1.1.0
github.com/docker/distribution v2.8.1+incompatible
github.com/docker/distribution v2.8.2+incompatible
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7
github.com/ghodss/yaml v1.0.0
github.com/go-asn1-ber/asn1-ber v1.5.1
@ -25,7 +25,7 @@ require (
github.com/go-openapi/runtime v0.19.20
github.com/go-openapi/spec v0.19.8
github.com/go-openapi/strfmt v0.19.5
github.com/go-openapi/swag v0.19.14
github.com/go-openapi/swag v0.22.3
github.com/go-openapi/validate v0.19.10
github.com/go-redis/redis/v8 v8.11.4
github.com/gocarina/gocsv v0.0.0-20210516172204-ca9e8a8ddea8
@ -47,43 +47,43 @@ require (
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/olekukonko/tablewriter v0.0.5
github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
github.com/opencontainers/image-spec v1.1.0-rc5
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.14.0
github.com/prometheus/client_golang v1.16.0
github.com/robfig/cron v1.0.0 // indirect
github.com/robfig/cron/v3 v3.0.0
github.com/spf13/viper v1.8.1
github.com/stretchr/testify v1.8.2
github.com/stretchr/testify v1.8.4
github.com/tencentcloud/tencentcloud-sdk-go v1.0.62
github.com/theupdateframework/notary v0.6.1
github.com/vmihailenco/msgpack/v5 v5.0.0-rc.2
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.22.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.22.0
go.opentelemetry.io/otel v1.14.0
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.44.0
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0
go.opentelemetry.io/otel v1.19.0
go.opentelemetry.io/otel/exporters/jaeger v1.0.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0
go.opentelemetry.io/otel/sdk v1.8.0
go.opentelemetry.io/otel/trace v1.14.0
go.opentelemetry.io/otel/trace v1.19.0
go.uber.org/ratelimit v0.2.0
golang.org/x/crypto v0.5.0
golang.org/x/net v0.9.0
golang.org/x/oauth2 v0.5.0
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8
golang.org/x/crypto v0.17.0
golang.org/x/net v0.17.0
golang.org/x/oauth2 v0.10.0
golang.org/x/time v0.3.0
gopkg.in/h2non/gock.v1 v1.0.16
gopkg.in/yaml.v2 v2.4.0
helm.sh/helm/v3 v3.11.3
k8s.io/api v0.26.2
k8s.io/apimachinery v0.26.2
k8s.io/client-go v0.26.2
helm.sh/helm/v3 v3.14.2
k8s.io/api v0.29.0
k8s.io/apimachinery v0.29.0
k8s.io/client-go v0.29.0
)
require (
github.com/beego/beego/v2 v2.0.6
golang.org/x/text v0.9.0
golang.org/x/text v0.14.0
)
require (
cloud.google.com/go/compute v1.18.0 // indirect
cloud.google.com/go/compute v1.23.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/Azure/azure-sdk-for-go v37.2.0+incompatible // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
@ -95,7 +95,7 @@ require (
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Microsoft/go-winio v0.5.1 // indirect
github.com/Unknwon/goconfig v0.0.0-20160216183935-5f601ca6ef4d // indirect
github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 // indirect
@ -113,14 +113,14 @@ require (
github.com/docker/go-metrics v0.0.1 // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/logr v1.3.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/analysis v0.19.10 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-stack/stack v1.8.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/certificate-transparency-go v1.0.21 // indirect
github.com/google/go-querystring v1.0.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
@ -142,7 +142,7 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/magiconair/properties v1.8.5 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect
@ -151,12 +151,12 @@ require (
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pelletier/go-toml v1.9.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.8.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
github.com/satori/go.uuid v1.2.0 // indirect
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/afero v1.6.0 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
@ -165,23 +165,23 @@ require (
github.com/subosito/gotenv v1.2.0 // indirect
github.com/vmihailenco/tagparser v0.1.2 // indirect
go.mongodb.org/mongo-driver v1.7.0 // indirect
go.opentelemetry.io/contrib v0.22.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0 // indirect
go.opentelemetry.io/otel/internal/metric v0.22.0 // indirect
go.opentelemetry.io/otel/metric v0.22.0 // indirect
go.opentelemetry.io/otel/metric v1.19.0 // indirect
go.opentelemetry.io/proto/otlp v0.11.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.19.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/term v0.7.0 // indirect
google.golang.org/api v0.110.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/term v0.15.0 // indirect
google.golang.org/api v0.126.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8 // indirect
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
google.golang.org/grpc v1.53.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
google.golang.org/grpc v1.58.3 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/dancannon/gorethink.v3 v3.0.5 // indirect
gopkg.in/fatih/pool.v2 v2.0.0 // indirect
gopkg.in/gorethink/gorethink.v3 v3.0.5 // indirect
@ -189,10 +189,10 @@ require (
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.90.1 // indirect
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
k8s.io/klog/v2 v2.110.1 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

View File

@ -20,8 +20,8 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY=
cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs=
cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY=
cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
@ -90,8 +90,8 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g=
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
@ -133,7 +133,6 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190726115642-cd293c93fd97 h1:bNE5ID4C3YOkROfvBjXJUG53gyb+8az3TQN02LqnGBk=
github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190726115642-cd293c93fd97/go.mod h1:myCDvQSzCW+wB1WAlocEru4wMGJxy+vlxHdhegi1CDQ=
@ -389,8 +388,8 @@ github.com/distribution/distribution v2.8.2+incompatible/go.mod h1:EgLm2NgWtdKgz
github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/docker/docker v20.10.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v20.10.24+incompatible h1:Ugvxm7a8+Gz6vqQYQQ2W7GYq5EUPaAiuPgIfVyI3dYE=
github.com/docker/docker v20.10.24+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/go v0.0.0-20160303222718-d30aec9fd63c h1:Ggg7IiOtghyZzn3ozi31kPHpV6qSjMgmesXaWCijYNM=
github.com/docker/go v0.0.0-20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q=
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
@ -420,8 +419,8 @@ github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkg
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful/v3 v3.10.1 h1:rc42Y5YTp7Am7CS630D7JmhRjq4UlEUuEKfrDac4bSQ=
github.com/emicklei/go-restful/v3 v3.10.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@ -435,7 +434,6 @@ github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/felixge/httpsnoop v1.0.2/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
@ -471,22 +469,19 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-latex/latex v0.0.0-20210118124228-b3d85cf34e07/go.mod h1:CO1AlKB2CSIqUrmQPqA0gdRIlnLEY0gK5JGjh37zN5U=
github.com/go-ldap/ldap/v3 v3.2.4 h1:PFavAq2xTgzo/loE8qNXcQaofAaqIpI4WgaLdv+1l3E=
github.com/go-ldap/ldap/v3 v3.2.4/go.mod h1:iYS1MdmrmceOJ1QOTnRXrIs7i3kloqtmGQjRvjKpyMg=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
@ -508,14 +503,14 @@ github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwds
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
@ -550,8 +545,8 @@ github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo=
@ -654,8 +649,9 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@ -668,8 +664,8 @@ github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ
github.com/google/certificate-transparency-go v1.0.21 h1:Yf1aXowfZ2nuboBsg7iYGLmwsOARdV86pfH3g95wXmE=
github.com/google/certificate-transparency-go v1.0.21/go.mod h1:QeJfpSbVSfYc7RgB3gJFj9cbuQMMchQxrWXz8Ruopmg=
github.com/google/flatbuffers v2.0.0+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@ -682,8 +678,9 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-github/v35 v35.2.0/go.mod h1:s0515YVTI+IMrDoy9Y4pHt9ShGpzHvHO8rZ7L7acgvs=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
@ -883,7 +880,6 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
@ -911,8 +907,8 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
@ -927,8 +923,8 @@ github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
@ -941,8 +937,8 @@ github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsIW75CHf65OeIOkyKbteujpZVXDpWK6YGZbxE=
github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
@ -995,8 +991,8 @@ github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2J
github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -1014,7 +1010,6 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mutecomm/go-sqlcipher/v4 v4.4.0/go.mod h1:PyN04SaWalavxRGH9E8ZftG6Ju7rsPrGmQRjrEaVpiY=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nakagami/firebirdsql v0.0.0-20190310045651-3c02a58cfed8/go.mod h1:86wM1zFnC6/uDBfZGNwB65O+pR2OFi5q/YQaEUid1qA=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
@ -1061,8 +1056,8 @@ github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.23.0 h1:/oxKu9c2HVap+F3PfKort2Hw5DEU+HGlW8n+tguWsys=
github.com/onsi/gomega v1.23.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg=
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@ -1070,8 +1065,8 @@ github.com/opencontainers/go-digest v1.0.0-rc1.0.20180430190053-c9281466c8b2/go.
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI=
github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opencontainers/runc v1.0.0-rc8.0.20190926000215-3e425f80a8c9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
@ -1134,18 +1129,16 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8=
github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY=
github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
@ -1153,10 +1146,8 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY=
github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
@ -1169,9 +1160,8 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg=
github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
@ -1185,8 +1175,8 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU=
github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc=
@ -1216,8 +1206,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
@ -1270,8 +1260,9 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@ -1346,20 +1337,14 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/contrib v0.22.0 h1:0F7gDEjgb1WGn4ODIjaCAg75hmqF+UN0LiVgwxsCodc=
go.opentelemetry.io/contrib v0.22.0/go.mod h1:EH4yDYeNoaTqn/8yCWQmfNB78VHfGX2Jt2bvnvzBlGM=
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.22.0 h1:Mfz1DMQ43mhQePKqiny6kUTnUrtin+395V67yAIyYhg=
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.22.0/go.mod h1:jpoprhHaffWHQ1KBpL0jI+w7979p4ijAL2auucLUj1E=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.22.0 h1:WHjZguqT+3UjTgFum33hWZYybDVnx8u9q5/kQDfaGTs=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.22.0/go.mod h1:o3MuU25bYroYnc2TOKe8mTk8f9X1oPFO6C5RCoPKtSU=
go.opentelemetry.io/contrib/propagators v0.22.0 h1:KGdv58M2//veiYLIhb31mofaI2LgkIPXXAZVeYVyfd8=
go.opentelemetry.io/contrib/propagators v0.22.0/go.mod h1:xGOuXr6lLIF9BXipA4pm6UuOSI0M98U6tsI3khbOiwU=
go.opentelemetry.io/otel v1.0.0-RC1/go.mod h1:x9tRa9HK4hSSq7jf2TKbqFbtt58/TGk0f9XiEYISI1I=
go.opentelemetry.io/otel v1.0.0-RC2/go.mod h1:w1thVQ7qbAy8MHb0IFj8a5Q2QU0l2ksf8u/CN8m3NOM=
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.44.0 h1:QaNUlLvmettd1vnmFHrgBYQHearxWP3uO4h4F3pVtkM=
go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.44.0/go.mod h1:cJu+5jZwoZfkBOECSFtBZK/O7h/pY5djn0fwnIGnQ4A=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q=
go.opentelemetry.io/otel v1.0.0/go.mod h1:AjRVh9A5/5DE7S+mZtTR6t8vpKKryam+0lREnfmS4cg=
go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs=
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
go.opentelemetry.io/otel/exporters/jaeger v1.0.0 h1:cLhx8llHw02h5JTqGqaRbYn+QVKHmrzD9vEbKnSPk5U=
go.opentelemetry.io/otel/exporters/jaeger v1.0.0/go.mod h1:q10N1AolE1JjqKrFJK2tYw0iZpmX+HBaXBtuCzRnBGQ=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.3.0 h1:R/OBkMoGgfy2fLhs2QhkCI1w4HLEQX92GCcJB6SSdNk=
@ -1368,23 +1353,16 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0 h1:giGm8w67Ja7amYNfYMdm
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.3.0/go.mod h1:hO1KLR7jcKaDDKDkvI9dP/FIhpmna5lkqPUQdEjFAM8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0 h1:Ydage/P0fRrSPpZeCVxzjqGcI6iVmG2xb43+IR8cjqM=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.3.0/go.mod h1:QNX1aly8ehqqX1LEa6YniTU7VY9I6R3X/oPxhGdTceE=
go.opentelemetry.io/otel/internal/metric v0.22.0 h1:Q9bS02XRykSRIbggaU4hVF9oWOP9PyILu26zJWoKmk0=
go.opentelemetry.io/otel/internal/metric v0.22.0/go.mod h1:7qVuMihW/ktMonEfOvBXuh6tfMvvEyoIDgeJNRloYbQ=
go.opentelemetry.io/otel/metric v0.22.0 h1:/qv10BzznqEifrXBwsTT370OCN1PRgt+mnjzMwxJKrQ=
go.opentelemetry.io/otel/metric v0.22.0/go.mod h1:KcsUkBiYGW003DJ+ugd2aqIRIfjabD9jeOUXqsAtrq0=
go.opentelemetry.io/otel/oteltest v1.0.0-RC1/go.mod h1:+eoIG0gdEOaPNftuy1YScLr1Gb4mL/9lpDkZ0JjMRq4=
go.opentelemetry.io/otel/oteltest v1.0.0-RC2 h1:xNKqMhlZYkASSyvF4JwObZFMq0jhFN3c3SP+2rCzVPk=
go.opentelemetry.io/otel/oteltest v1.0.0-RC2/go.mod h1:kiQ4tw5tAL4JLTbcOYwK1CWI1HkT5aiLzHovgOVnz/A=
go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
go.opentelemetry.io/otel/sdk v1.0.0/go.mod h1:PCrDHlSy5x1kjezSdL37PhbFUMjrsLRshJ2zCzeXwbM=
go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs=
go.opentelemetry.io/otel/sdk v1.8.0 h1:xwu69/fNuwbSHWe/0PGS888RmjWY181OmcXDQKu7ZQk=
go.opentelemetry.io/otel/sdk v1.8.0/go.mod h1:uPSfc+yfDH2StDM/Rm35WE8gXSNdvCg023J6HeGNO0c=
go.opentelemetry.io/otel/trace v1.0.0-RC1/go.mod h1:86UHmyHWFEtWjfWPSbu0+d0Pf9Q6e1U+3ViBOc+NXAg=
go.opentelemetry.io/otel/trace v1.0.0-RC2/go.mod h1:JPQ+z6nNw9mqEGT8o3eoPTdnNI+Aj5JcxEsVGREIAy4=
go.opentelemetry.io/otel/trace v1.0.0/go.mod h1:PXTWqayeFUlJV1YDNhsJYB184+IvAH814St6o6ajzIs=
go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk=
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v0.11.0 h1:cLDgIBTf4lLOlztkhzAEdQsJ4Lj+i5Wc9k6Nn0K1VyU=
go.opentelemetry.io/proto/otlp v0.11.0/go.mod h1:QpEjXPrNQzrFDZgoTo49dgHR9RYRSrg3NAKnUGl9YpQ=
@ -1440,8 +1418,8 @@ golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5y
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -1541,15 +1519,12 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
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-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211013171255-e13a2654a71e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -1557,11 +1532,9 @@ golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s=
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -1637,7 +1610,6 @@ golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200817155316-9781c653f443/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1661,23 +1633,19 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/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-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210818153620-00dd8d7831e7/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1687,15 +1655,15 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -1762,8 +1730,8 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss=
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -1827,8 +1795,12 @@ google.golang.org/genproto v0.0.0-20210630183607-d20f26d13c79/go.mod h1:yiaVoXHp
google.golang.org/genproto v0.0.0-20210721163202-f1cecdd8b78a/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210726143408-b02e89920bf0/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20211013025323-ce878158c4d4/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA=
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g=
google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8=
google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e h1:z3vDksarJxsAKM5dmEGv0GHwE2hKJ096wZra71Vs4sw=
google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
@ -1857,8 +1829,8 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ=
google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@ -1873,8 +1845,8 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@ -1935,8 +1907,8 @@ gorm.io/gorm v1.21.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
helm.sh/helm/v3 v3.11.3 h1:n1X5yaQTP5DYywlBOZMl2gX398Gp6YwFp/IAVj6+5D4=
helm.sh/helm/v3 v3.11.3/go.mod h1:S+sOdQc3BLvt09a9rSlKKVs9x0N/yx+No0y3qFw+FQ8=
helm.sh/helm/v3 v3.14.2 h1:V71fv+NGZv0icBlr+in1MJXuUIHCiPG1hW9gEBISTIA=
helm.sh/helm/v3 v3.14.2/go.mod h1:2itvvDv2WSZXTllknfQo6j7u3VVgMAvm8POCDgYH424=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@ -1948,21 +1920,21 @@ honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo=
k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ=
k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
k8s.io/api v0.26.2 h1:dM3cinp3PGB6asOySalOZxEG4CZ0IAdJsrYZXE/ovGQ=
k8s.io/api v0.26.2/go.mod h1:1kjMQsFE+QHPfskEcVNgL3+Hp88B80uj0QtSOlj8itU=
k8s.io/api v0.29.0 h1:NiCdQMY1QOp1H8lfRyeEf8eOwV6+0xA6XEE44ohDX2A=
k8s.io/api v0.29.0/go.mod h1:sdVmXoz2Bo/cb77Pxi71IPTSErEW32xa4aXwKH7gfBA=
k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc=
k8s.io/apimachinery v0.26.2 h1:da1u3D5wfR5u2RpLhE/ZtZS2P7QvDgLZTi9wrNZl/tQ=
k8s.io/apimachinery v0.26.2/go.mod h1:ats7nN1LExKHvJ9TmwootT00Yz05MuYqPXEXaVeOy5I=
k8s.io/apimachinery v0.29.0 h1:+ACVktwyicPz0oc6MTMLwa2Pw3ouLAfAon1wPLtG48o=
k8s.io/apimachinery v0.29.0/go.mod h1:eVBxQ/cwiJxH58eK/jd/vAk4mrxmVlnpBH5J2GbMeis=
k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU=
k8s.io/apiserver v0.20.4/go.mod h1:Mc80thBKOyy7tbvFtB4kJv1kbdD0eIH8k8vianJcbFM=
k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q=
k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y=
k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k=
k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0=
k8s.io/client-go v0.26.2 h1:s1WkVujHX3kTp4Zn4yGNFK+dlDXy1bAAkIl+cFAiuYI=
k8s.io/client-go v0.26.2/go.mod h1:u5EjOuSyBa09yqqyY7m3abZeovO/7D/WehVVlZ2qcqU=
k8s.io/client-go v0.29.0 h1:KmlDtFcrdUzOYrBhXHgKw5ycWzc3ryPX5mQe0SkG3y8=
k8s.io/client-go v0.29.0/go.mod h1:yLkXH4HKMAywcrD82KMSmfYg2DlE8mepPR4JGSo5n38=
k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk=
k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI=
k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM=
@ -1973,15 +1945,15 @@ k8s.io/cri-api v0.20.6/go.mod h1:ew44AjNXwyn1s0U4xCKGodU7J1HzBeZ1MpGrpa5r8Yc=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.90.1 h1:m4bYOKall2MmOiRaR1J+We67Do7vm9KiQVlT96lnHUw=
k8s.io/klog/v2 v2.90.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 h1:+70TFaan3hfJzs+7VK2o+OGxg8HsuBr/5f6tVAjDu6E=
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5 h1:kmDqav+P+/5e1i9tFfHq1qcF3sOrDp+YEkVDAHu7Jwk=
k8s.io/utils v0.0.0-20230220204549-a5ecb0141aa5/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
modernc.org/b v1.0.0/go.mod h1:uZWcZfRj1BpYzfN9JTerzlNUnnPsV9O2ZA8JsRcubNg=
modernc.org/cc/v3 v3.32.4/go.mod h1:0R6jl1aZlIl2avnYfbfHBS1QB6/f+16mihBObaBC878=
modernc.org/ccgo/v3 v3.9.2/go.mod h1:gnJpy6NIVqkETT+L5zPsQFj7L2kkhfPMzOghRNv/CFo=
@ -2014,12 +1986,12 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=

View File

@ -15,4 +15,4 @@
package internal
// Version is the current tagged release of the library.
const Version = "1.18.0"
const Version = "1.23.0"

View File

@ -5,12 +5,9 @@ linters:
disable-all: true
enable:
- misspell
- structcheck
- govet
- staticcheck
- deadcode
- errcheck
- varcheck
- unparam
- ineffassign
- nakedret

View File

@ -1,7 +1,5 @@
GOPATH=$(shell go env GOPATH)
GOLANGCI_LINT=$(GOPATH)/bin/golangci-lint
GOFUZZBUILD = $(GOPATH)/bin/go-fuzz-build
GOFUZZ = $(GOPATH)/bin/go-fuzz
.PHONY: lint
lint: $(GOLANGCI_LINT)
@ -19,19 +17,14 @@ test-cover:
GO111MODULE=on go test -cover .
.PHONY: fuzz
fuzz: $(GOFUZZBUILD) $(GOFUZZ)
@echo "==> Fuzz testing"
$(GOFUZZBUILD)
$(GOFUZZ) -workdir=_fuzz
fuzz:
@echo "==> Running Fuzz Tests"
go test -fuzz=FuzzNewVersion -fuzztime=15s .
go test -fuzz=FuzzStrictNewVersion -fuzztime=15s .
go test -fuzz=FuzzNewConstraint -fuzztime=15s .
$(GOLANGCI_LINT):
# Install golangci-lint. The configuration for it is in the .golangci.yml
# file in the root of the repository
echo ${GOPATH}
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOPATH)/bin v1.17.1
$(GOFUZZBUILD):
cd / && go get -u github.com/dvyukov/go-fuzz/go-fuzz-build
$(GOFUZZ):
cd / && go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-dep

View File

@ -18,18 +18,20 @@ If you are looking for a command line tool for version comparisons please see
## Package Versions
Note, import `github.com/github.com/Masterminds/semver/v3` to use the latest version.
There are three major versions fo the `semver` package.
* 3.x.x is the new stable and active version. This version is focused on constraint
* 3.x.x is the stable and active version. This version is focused on constraint
compatibility for range handling in other tools from other languages. It has
a similar API to the v1 releases. The development of this version is on the master
branch. The documentation for this version is below.
* 2.x was developed primarily for [dep](https://github.com/golang/dep). There are
no tagged releases and the development was performed by [@sdboyer](https://github.com/sdboyer).
There are API breaking changes from v1. This version lives on the [2.x branch](https://github.com/Masterminds/semver/tree/2.x).
* 1.x.x is the most widely used version with numerous tagged releases. This is the
previous stable and is still maintained for bug fixes. The development, to fix
bugs, occurs on the release-1 branch. You can read the documentation [here](https://github.com/Masterminds/semver/blob/release-1/README.md).
* 1.x.x is the original release. It is no longer maintained. You should use the
v3 release instead. You can read the documentation for the 1.x.x release
[here](https://github.com/Masterminds/semver/blob/release-1/README.md).
## Parsing Semantic Versions
@ -242,3 +244,15 @@ for _, m := range msgs {
If you find an issue or want to contribute please file an [issue](https://github.com/Masterminds/semver/issues)
or [create a pull request](https://github.com/Masterminds/semver/pulls).
## Security
Security is an important consideration for this project. The project currently
uses the following tools to help discover security issues:
* [CodeQL](https://github.com/Masterminds/semver)
* [gosec](https://github.com/securego/gosec)
* Daily Fuzz testing
If you believe you have found a security vulnerability you can privately disclose
it through the [GitHub security page](https://github.com/Masterminds/semver/security).

View File

@ -0,0 +1,19 @@
# Security Policy
## Supported Versions
The following versions of semver are currently supported:
| Version | Supported |
| ------- | ------------------ |
| 3.x | :white_check_mark: |
| 2.x | :x: |
| 1.x | :x: |
Fixes are only released for the latest minor version in the form of a patch release.
## Reporting a Vulnerability
You can privately disclose a vulnerability through GitHubs
[private vulnerability reporting](https://github.com/Masterminds/semver/security/advisories)
mechanism.

View File

@ -586,7 +586,7 @@ func rewriteRange(i string) string {
}
o := i
for _, v := range m {
t := fmt.Sprintf(">= %s, <= %s", v[1], v[11])
t := fmt.Sprintf(">= %s, <= %s ", v[1], v[11])
o = strings.Replace(o, v[0], t, 1)
}

View File

@ -1,22 +0,0 @@
// +build gofuzz
package semver
func Fuzz(data []byte) int {
d := string(data)
// Test NewVersion
_, _ = NewVersion(d)
// Test StrictNewVersion
_, _ = StrictNewVersion(d)
// Test NewConstraint
_, _ = NewConstraint(d)
// The return value should be 0 normally, 1 if the priority in future tests
// should be increased, and -1 if future tests should skip passing in that
// data. We do not have a reason to change priority so 0 is always returned.
// There are example tests that do this.
return 0
}

View File

@ -6,7 +6,6 @@ linters:
disable-all: true
enable:
- asciicheck
- deadcode
- errcheck
- forcetypeassert
- gocritic
@ -18,10 +17,8 @@ linters:
- misspell
- revive
- staticcheck
- structcheck
- typecheck
- unused
- varcheck
issues:
exclude-use-default: false

View File

@ -1,6 +1,7 @@
# A minimal logging API for Go
[![Go Reference](https://pkg.go.dev/badge/github.com/go-logr/logr.svg)](https://pkg.go.dev/github.com/go-logr/logr)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/go-logr/logr/badge)](https://securityscorecards.dev/viewer/?platform=github.com&org=go-logr&repo=logr)
logr offers an(other) opinion on how Go programs and libraries can do logging
without becoming coupled to a particular logging implementation. This is not
@ -73,6 +74,29 @@ received:
If the Go standard library had defined an interface for logging, this project
probably would not be needed. Alas, here we are.
When the Go developers started developing such an interface with
[slog](https://github.com/golang/go/issues/56345), they adopted some of the
logr design but also left out some parts and changed others:
| Feature | logr | slog |
|---------|------|------|
| High-level API | `Logger` (passed by value) | `Logger` (passed by [pointer](https://github.com/golang/go/issues/59126)) |
| Low-level API | `LogSink` | `Handler` |
| Stack unwinding | done by `LogSink` | done by `Logger` |
| Skipping helper functions | `WithCallDepth`, `WithCallStackHelper` | [not supported by Logger](https://github.com/golang/go/issues/59145) |
| Generating a value for logging on demand | `Marshaler` | `LogValuer` |
| Log levels | >= 0, higher meaning "less important" | positive and negative, with 0 for "info" and higher meaning "more important" |
| Error log entries | always logged, don't have a verbosity level | normal log entries with level >= `LevelError` |
| Passing logger via context | `NewContext`, `FromContext` | no API |
| Adding a name to a logger | `WithName` | no API |
| Modify verbosity of log entries in a call chain | `V` | no API |
| Grouping of key/value pairs | not supported | `WithGroup`, `GroupValue` |
The high-level slog API is explicitly meant to be one of many different APIs
that can be layered on top of a shared `slog.Handler`. logr is one such
alternative API, with [interoperability](#slog-interoperability) provided by the [`slogr`](slogr)
package.
### Inspiration
Before you consider this package, please read [this blog post by the
@ -118,6 +142,91 @@ There are implementations for the following logging libraries:
- **github.com/go-kit/log**: [gokitlogr](https://github.com/tonglil/gokitlogr) (also compatible with github.com/go-kit/kit/log since v0.12.0)
- **bytes.Buffer** (writing to a buffer): [bufrlogr](https://github.com/tonglil/buflogr) (useful for ensuring values were logged, like during testing)
## slog interoperability
Interoperability goes both ways, using the `logr.Logger` API with a `slog.Handler`
and using the `slog.Logger` API with a `logr.LogSink`. [slogr](./slogr) provides `NewLogr` and
`NewSlogHandler` API calls to convert between a `logr.Logger` and a `slog.Handler`.
As usual, `slog.New` can be used to wrap such a `slog.Handler` in the high-level
slog API. `slogr` itself leaves that to the caller.
## Using a `logr.Sink` as backend for slog
Ideally, a logr sink implementation should support both logr and slog by
implementing both the normal logr interface(s) and `slogr.SlogSink`. Because
of a conflict in the parameters of the common `Enabled` method, it is [not
possible to implement both slog.Handler and logr.Sink in the same
type](https://github.com/golang/go/issues/59110).
If both are supported, log calls can go from the high-level APIs to the backend
without the need to convert parameters. `NewLogr` and `NewSlogHandler` can
convert back and forth without adding additional wrappers, with one exception:
when `Logger.V` was used to adjust the verbosity for a `slog.Handler`, then
`NewSlogHandler` has to use a wrapper which adjusts the verbosity for future
log calls.
Such an implementation should also support values that implement specific
interfaces from both packages for logging (`logr.Marshaler`, `slog.LogValuer`,
`slog.GroupValue`). logr does not convert those.
Not supporting slog has several drawbacks:
- Recording source code locations works correctly if the handler gets called
through `slog.Logger`, but may be wrong in other cases. That's because a
`logr.Sink` does its own stack unwinding instead of using the program counter
provided by the high-level API.
- slog levels <= 0 can be mapped to logr levels by negating the level without a
loss of information. But all slog levels > 0 (e.g. `slog.LevelWarning` as
used by `slog.Logger.Warn`) must be mapped to 0 before calling the sink
because logr does not support "more important than info" levels.
- The slog group concept is supported by prefixing each key in a key/value
pair with the group names, separated by a dot. For structured output like
JSON it would be better to group the key/value pairs inside an object.
- Special slog values and interfaces don't work as expected.
- The overhead is likely to be higher.
These drawbacks are severe enough that applications using a mixture of slog and
logr should switch to a different backend.
## Using a `slog.Handler` as backend for logr
Using a plain `slog.Handler` without support for logr works better than the
other direction:
- All logr verbosity levels can be mapped 1:1 to their corresponding slog level
by negating them.
- Stack unwinding is done by the `slogr.SlogSink` and the resulting program
counter is passed to the `slog.Handler`.
- Names added via `Logger.WithName` are gathered and recorded in an additional
attribute with `logger` as key and the names separated by slash as value.
- `Logger.Error` is turned into a log record with `slog.LevelError` as level
and an additional attribute with `err` as key, if an error was provided.
The main drawback is that `logr.Marshaler` will not be supported. Types should
ideally support both `logr.Marshaler` and `slog.Valuer`. If compatibility
with logr implementations without slog support is not important, then
`slog.Valuer` is sufficient.
## Context support for slog
Storing a logger in a `context.Context` is not supported by
slog. `logr.NewContext` and `logr.FromContext` can be used with slog like this
to fill this gap:
func HandlerFromContext(ctx context.Context) slog.Handler {
logger, err := logr.FromContext(ctx)
if err == nil {
return slogr.NewSlogHandler(logger)
}
return slog.Default().Handler()
}
func ContextWithHandler(ctx context.Context, handler slog.Handler) context.Context {
return logr.NewContext(ctx, slogr.NewLogr(handler))
}
The downside is that storing and retrieving a `slog.Handler` needs more
allocations compared to using a `logr.Logger`. Therefore the recommendation is
to use the `logr.Logger` API in code which uses contextual logging.
## FAQ
### Conceptual
@ -241,7 +350,9 @@ Otherwise, you can start out with `0` as "you always want to see this",
Then gradually choose levels in between as you need them, working your way
down from 10 (for debug and trace style logs) and up from 1 (for chattier
info-type logs.)
info-type logs). For reference, slog pre-defines -4 for debug logs
(corresponds to 4 in logr), which matches what is
[recommended for Kubernetes](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md#what-method-to-use).
#### How do I choose my keys?

18
src/vendor/github.com/go-logr/logr/SECURITY.md generated vendored Normal file
View File

@ -0,0 +1,18 @@
# Security Policy
If you have discovered a security vulnerability in this project, please report it
privately. **Do not disclose it as a public issue.** This gives us time to work with you
to fix the issue before public exposure, reducing the chance that the exploit will be
used before a patch is released.
You may submit the report in the following ways:
- send an email to go-logr-security@googlegroups.com
- send us a [private vulnerability report](https://github.com/go-logr/logr/security/advisories/new)
Please provide the following information in your report:
- A description of the vulnerability and its impact
- How to reproduce the issue
We ask that you give us 90 days to work on a fix before public exposure.

View File

@ -20,35 +20,5 @@ package logr
// used whenever the caller is not interested in the logs. Logger instances
// produced by this function always compare as equal.
func Discard() Logger {
return Logger{
level: 0,
sink: discardLogSink{},
}
}
// discardLogSink is a LogSink that discards all messages.
type discardLogSink struct{}
// Verify that it actually implements the interface
var _ LogSink = discardLogSink{}
func (l discardLogSink) Init(RuntimeInfo) {
}
func (l discardLogSink) Enabled(int) bool {
return false
}
func (l discardLogSink) Info(int, string, ...interface{}) {
}
func (l discardLogSink) Error(error, string, ...interface{}) {
}
func (l discardLogSink) WithValues(...interface{}) LogSink {
return l
}
func (l discardLogSink) WithName(string) LogSink {
return l
return New(nil)
}

View File

@ -21,13 +21,13 @@ limitations under the License.
// github.com/go-logr/logr.LogSink with output through an arbitrary
// "write" function. See New and NewJSON for details.
//
// Custom LogSinks
// # Custom LogSinks
//
// For users who need more control, a funcr.Formatter can be embedded inside
// your own custom LogSink implementation. This is useful when the LogSink
// needs to implement additional methods, for example.
//
// Formatting
// # Formatting
//
// This will respect logr.Marshaler, fmt.Stringer, and error interfaces for
// values which are being logged. When rendering a struct, funcr will use Go's
@ -37,6 +37,7 @@ package funcr
import (
"bytes"
"encoding"
"encoding/json"
"fmt"
"path/filepath"
"reflect"
@ -115,17 +116,17 @@ type Options struct {
// Equivalent hooks are offered for key-value pairs saved via
// logr.Logger.WithValues or Formatter.AddValues (see RenderValuesHook) and
// for user-provided pairs (see RenderArgsHook).
RenderBuiltinsHook func(kvList []interface{}) []interface{}
RenderBuiltinsHook func(kvList []any) []any
// RenderValuesHook is the same as RenderBuiltinsHook, except that it is
// only called for key-value pairs saved via logr.Logger.WithValues. See
// RenderBuiltinsHook for more details.
RenderValuesHook func(kvList []interface{}) []interface{}
RenderValuesHook func(kvList []any) []any
// RenderArgsHook is the same as RenderBuiltinsHook, except that it is only
// called for key-value pairs passed directly to Info and Error. See
// RenderBuiltinsHook for more details.
RenderArgsHook func(kvList []interface{}) []interface{}
RenderArgsHook func(kvList []any) []any
// MaxLogDepth tells funcr how many levels of nested fields (e.g. a struct
// that contains a struct, etc.) it may log. Every time it finds a struct,
@ -162,7 +163,7 @@ func (l fnlogger) WithName(name string) logr.LogSink {
return &l
}
func (l fnlogger) WithValues(kvList ...interface{}) logr.LogSink {
func (l fnlogger) WithValues(kvList ...any) logr.LogSink {
l.Formatter.AddValues(kvList)
return &l
}
@ -172,12 +173,12 @@ func (l fnlogger) WithCallDepth(depth int) logr.LogSink {
return &l
}
func (l fnlogger) Info(level int, msg string, kvList ...interface{}) {
func (l fnlogger) Info(level int, msg string, kvList ...any) {
prefix, args := l.FormatInfo(level, msg, kvList)
l.write(prefix, args)
}
func (l fnlogger) Error(err error, msg string, kvList ...interface{}) {
func (l fnlogger) Error(err error, msg string, kvList ...any) {
prefix, args := l.FormatError(err, msg, kvList)
l.write(prefix, args)
}
@ -217,7 +218,7 @@ func newFormatter(opts Options, outfmt outputFormat) Formatter {
prefix: "",
values: nil,
depth: 0,
opts: opts,
opts: &opts,
}
return f
}
@ -228,10 +229,10 @@ func newFormatter(opts Options, outfmt outputFormat) Formatter {
type Formatter struct {
outputFormat outputFormat
prefix string
values []interface{}
values []any
valuesStr string
depth int
opts Options
opts *Options
}
// outputFormat indicates which outputFormat to use.
@ -245,10 +246,10 @@ const (
)
// PseudoStruct is a list of key-value pairs that gets logged as a struct.
type PseudoStruct []interface{}
type PseudoStruct []any
// render produces a log line, ready to use.
func (f Formatter) render(builtins, args []interface{}) string {
func (f Formatter) render(builtins, args []any) string {
// Empirically bytes.Buffer is faster than strings.Builder for this.
buf := bytes.NewBuffer(make([]byte, 0, 1024))
if f.outputFormat == outputJSON {
@ -291,7 +292,7 @@ func (f Formatter) render(builtins, args []interface{}) string {
// This function returns a potentially modified version of kvList, which
// ensures that there is a value for every key (adding a value if needed) and
// that each key is a string (substituting a key if needed).
func (f Formatter) flatten(buf *bytes.Buffer, kvList []interface{}, continuing bool, escapeKeys bool) []interface{} {
func (f Formatter) flatten(buf *bytes.Buffer, kvList []any, continuing bool, escapeKeys bool) []any {
// This logic overlaps with sanitize() but saves one type-cast per key,
// which can be measurable.
if len(kvList)%2 != 0 {
@ -333,7 +334,7 @@ func (f Formatter) flatten(buf *bytes.Buffer, kvList []interface{}, continuing b
return kvList
}
func (f Formatter) pretty(value interface{}) string {
func (f Formatter) pretty(value any) string {
return f.prettyWithFlags(value, 0, 0)
}
@ -342,7 +343,7 @@ const (
)
// TODO: This is not fast. Most of the overhead goes here.
func (f Formatter) prettyWithFlags(value interface{}, flags uint32, depth int) string {
func (f Formatter) prettyWithFlags(value any, flags uint32, depth int) string {
if depth > f.opts.MaxLogDepth {
return `"<max-log-depth-exceeded>"`
}
@ -447,6 +448,7 @@ func (f Formatter) prettyWithFlags(value interface{}, flags uint32, depth int) s
if flags&flagRawStruct == 0 {
buf.WriteByte('{')
}
printComma := false // testing i>0 is not enough because of JSON omitted fields
for i := 0; i < t.NumField(); i++ {
fld := t.Field(i)
if fld.PkgPath != "" {
@ -478,9 +480,10 @@ func (f Formatter) prettyWithFlags(value interface{}, flags uint32, depth int) s
if omitempty && isEmpty(v.Field(i)) {
continue
}
if i > 0 {
if printComma {
buf.WriteByte(',')
}
printComma = true // if we got here, we are rendering a field
if fld.Anonymous && fld.Type.Kind() == reflect.Struct && name == "" {
buf.WriteString(f.prettyWithFlags(v.Field(i).Interface(), flags|flagRawStruct, depth+1))
continue
@ -500,6 +503,20 @@ func (f Formatter) prettyWithFlags(value interface{}, flags uint32, depth int) s
}
return buf.String()
case reflect.Slice, reflect.Array:
// If this is outputing as JSON make sure this isn't really a json.RawMessage.
// If so just emit "as-is" and don't pretty it as that will just print
// it as [X,Y,Z,...] which isn't terribly useful vs the string form you really want.
if f.outputFormat == outputJSON {
if rm, ok := value.(json.RawMessage); ok {
// If it's empty make sure we emit an empty value as the array style would below.
if len(rm) > 0 {
buf.Write(rm)
} else {
buf.WriteString("null")
}
return buf.String()
}
}
buf.WriteByte('[')
for i := 0; i < v.Len(); i++ {
if i > 0 {
@ -597,7 +614,7 @@ func isEmpty(v reflect.Value) bool {
return false
}
func invokeMarshaler(m logr.Marshaler) (ret interface{}) {
func invokeMarshaler(m logr.Marshaler) (ret any) {
defer func() {
if r := recover(); r != nil {
ret = fmt.Sprintf("<panic: %s>", r)
@ -658,12 +675,12 @@ func (f Formatter) caller() Caller {
const noValue = "<no-value>"
func (f Formatter) nonStringKey(v interface{}) string {
func (f Formatter) nonStringKey(v any) string {
return fmt.Sprintf("<non-string-key: %s>", f.snippet(v))
}
// snippet produces a short snippet string of an arbitrary value.
func (f Formatter) snippet(v interface{}) string {
func (f Formatter) snippet(v any) string {
const snipLen = 16
snip := f.pretty(v)
@ -676,7 +693,7 @@ func (f Formatter) snippet(v interface{}) string {
// sanitize ensures that a list of key-value pairs has a value for every key
// (adding a value if needed) and that each key is a string (substituting a key
// if needed).
func (f Formatter) sanitize(kvList []interface{}) []interface{} {
func (f Formatter) sanitize(kvList []any) []any {
if len(kvList)%2 != 0 {
kvList = append(kvList, noValue)
}
@ -710,8 +727,8 @@ func (f Formatter) GetDepth() int {
// FormatInfo renders an Info log message into strings. The prefix will be
// empty when no names were set (via AddNames), or when the output is
// configured for JSON.
func (f Formatter) FormatInfo(level int, msg string, kvList []interface{}) (prefix, argsStr string) {
args := make([]interface{}, 0, 64) // using a constant here impacts perf
func (f Formatter) FormatInfo(level int, msg string, kvList []any) (prefix, argsStr string) {
args := make([]any, 0, 64) // using a constant here impacts perf
prefix = f.prefix
if f.outputFormat == outputJSON {
args = append(args, "logger", prefix)
@ -728,10 +745,10 @@ func (f Formatter) FormatInfo(level int, msg string, kvList []interface{}) (pref
}
// FormatError renders an Error log message into strings. The prefix will be
// empty when no names were set (via AddNames), or when the output is
// empty when no names were set (via AddNames), or when the output is
// configured for JSON.
func (f Formatter) FormatError(err error, msg string, kvList []interface{}) (prefix, argsStr string) {
args := make([]interface{}, 0, 64) // using a constant here impacts perf
func (f Formatter) FormatError(err error, msg string, kvList []any) (prefix, argsStr string) {
args := make([]any, 0, 64) // using a constant here impacts perf
prefix = f.prefix
if f.outputFormat == outputJSON {
args = append(args, "logger", prefix)
@ -744,12 +761,12 @@ func (f Formatter) FormatError(err error, msg string, kvList []interface{}) (pre
args = append(args, "caller", f.caller())
}
args = append(args, "msg", msg)
var loggableErr interface{}
var loggableErr any
if err != nil {
loggableErr = err.Error()
}
args = append(args, "error", loggableErr)
return f.prefix, f.render(args, kvList)
return prefix, f.render(args, kvList)
}
// AddName appends the specified name. funcr uses '/' characters to separate
@ -764,7 +781,7 @@ func (f *Formatter) AddName(name string) {
// AddValues adds key-value pairs to the set of saved values to be logged with
// each log line.
func (f *Formatter) AddValues(kvList []interface{}) {
func (f *Formatter) AddValues(kvList []any) {
// Three slice args forces a copy.
n := len(f.values)
f.values = append(f.values[:n:n], kvList...)

View File

@ -21,7 +21,7 @@ limitations under the License.
// to back that API. Packages in the Go ecosystem can depend on this package,
// while callers can implement logging with whatever backend is appropriate.
//
// Usage
// # Usage
//
// Logging is done using a Logger instance. Logger is a concrete type with
// methods, which defers the actual logging to a LogSink interface. The main
@ -30,16 +30,20 @@ limitations under the License.
// "structured logging".
//
// With Go's standard log package, we might write:
// log.Printf("setting target value %s", targetValue)
//
// log.Printf("setting target value %s", targetValue)
//
// With logr's structured logging, we'd write:
// logger.Info("setting target", "value", targetValue)
//
// logger.Info("setting target", "value", targetValue)
//
// Errors are much the same. Instead of:
// log.Printf("failed to open the pod bay door for user %s: %v", user, err)
//
// log.Printf("failed to open the pod bay door for user %s: %v", user, err)
//
// We'd write:
// logger.Error(err, "failed to open the pod bay door", "user", user)
//
// logger.Error(err, "failed to open the pod bay door", "user", user)
//
// Info() and Error() are very similar, but they are separate methods so that
// LogSink implementations can choose to do things like attach additional
@ -47,7 +51,7 @@ limitations under the License.
// always logged, regardless of the current verbosity. If there is no error
// instance available, passing nil is valid.
//
// Verbosity
// # Verbosity
//
// Often we want to log information only when the application in "verbose
// mode". To write log lines that are more verbose, Logger has a V() method.
@ -58,20 +62,22 @@ limitations under the License.
// Error messages do not have a verbosity level and are always logged.
//
// Where we might have written:
// if flVerbose >= 2 {
// log.Printf("an unusual thing happened")
// }
//
// if flVerbose >= 2 {
// log.Printf("an unusual thing happened")
// }
//
// We can write:
// logger.V(2).Info("an unusual thing happened")
//
// Logger Names
// logger.V(2).Info("an unusual thing happened")
//
// # Logger Names
//
// Logger instances can have name strings so that all messages logged through
// that instance have additional context. For example, you might want to add
// a subsystem name:
//
// logger.WithName("compactor").Info("started", "time", time.Now())
// logger.WithName("compactor").Info("started", "time", time.Now())
//
// The WithName() method returns a new Logger, which can be passed to
// constructors or other functions for further use. Repeated use of WithName()
@ -82,25 +88,27 @@ limitations under the License.
// joining operation (e.g. whitespace, commas, periods, slashes, brackets,
// quotes, etc).
//
// Saved Values
// # Saved Values
//
// Logger instances can store any number of key/value pairs, which will be
// logged alongside all messages logged through that instance. For example,
// you might want to create a Logger instance per managed object:
//
// With the standard log package, we might write:
// log.Printf("decided to set field foo to value %q for object %s/%s",
// targetValue, object.Namespace, object.Name)
//
// log.Printf("decided to set field foo to value %q for object %s/%s",
// targetValue, object.Namespace, object.Name)
//
// With logr we'd write:
// // Elsewhere: set up the logger to log the object name.
// obj.logger = mainLogger.WithValues(
// "name", obj.name, "namespace", obj.namespace)
//
// // later on...
// obj.logger.Info("setting foo", "value", targetValue)
// // Elsewhere: set up the logger to log the object name.
// obj.logger = mainLogger.WithValues(
// "name", obj.name, "namespace", obj.namespace)
//
// Best Practices
// // later on...
// obj.logger.Info("setting foo", "value", targetValue)
//
// # Best Practices
//
// Logger has very few hard rules, with the goal that LogSink implementations
// might have a lot of freedom to differentiate. There are, however, some
@ -119,20 +127,20 @@ limitations under the License.
// such a value can call its methods without having to check whether the
// instance is ready for use.
//
// Calling methods with the null logger (Logger{}) as instance will crash
// because it has no LogSink. Therefore this null logger should never be passed
// around. For cases where passing a logger is optional, a pointer to Logger
// The zero logger (= Logger{}) is identical to Discard() and discards all log
// entries. Code that receives a Logger by value can simply call it, the methods
// will never crash. For cases where passing a logger is optional, a pointer to Logger
// should be used.
//
// Key Naming Conventions
// # Key Naming Conventions
//
// Keys are not strictly required to conform to any specification or regex, but
// it is recommended that they:
// * be human-readable and meaningful (not auto-generated or simple ordinals)
// * be constant (not dependent on input data)
// * contain only printable characters
// * not contain whitespace or punctuation
// * use lower case for simple keys and lowerCamelCase for more complex ones
// - be human-readable and meaningful (not auto-generated or simple ordinals)
// - be constant (not dependent on input data)
// - contain only printable characters
// - not contain whitespace or punctuation
// - use lower case for simple keys and lowerCamelCase for more complex ones
//
// These guidelines help ensure that log data is processed properly regardless
// of the log implementation. For example, log implementations will try to
@ -141,51 +149,54 @@ limitations under the License.
// While users are generally free to use key names of their choice, it's
// generally best to avoid using the following keys, as they're frequently used
// by implementations:
// * "caller": the calling information (file/line) of a particular log line
// * "error": the underlying error value in the `Error` method
// * "level": the log level
// * "logger": the name of the associated logger
// * "msg": the log message
// * "stacktrace": the stack trace associated with a particular log line or
// error (often from the `Error` message)
// * "ts": the timestamp for a log line
// - "caller": the calling information (file/line) of a particular log line
// - "error": the underlying error value in the `Error` method
// - "level": the log level
// - "logger": the name of the associated logger
// - "msg": the log message
// - "stacktrace": the stack trace associated with a particular log line or
// error (often from the `Error` message)
// - "ts": the timestamp for a log line
//
// Implementations are encouraged to make use of these keys to represent the
// above concepts, when necessary (for example, in a pure-JSON output form, it
// would be necessary to represent at least message and timestamp as ordinary
// named values).
//
// Break Glass
// # Break Glass
//
// Implementations may choose to give callers access to the underlying
// logging implementation. The recommended pattern for this is:
// // Underlier exposes access to the underlying logging implementation.
// // Since callers only have a logr.Logger, they have to know which
// // implementation is in use, so this interface is less of an abstraction
// // and more of way to test type conversion.
// type Underlier interface {
// GetUnderlying() <underlying-type>
// }
//
// // Underlier exposes access to the underlying logging implementation.
// // Since callers only have a logr.Logger, they have to know which
// // implementation is in use, so this interface is less of an abstraction
// // and more of way to test type conversion.
// type Underlier interface {
// GetUnderlying() <underlying-type>
// }
//
// Logger grants access to the sink to enable type assertions like this:
// func DoSomethingWithImpl(log logr.Logger) {
// if underlier, ok := log.GetSink()(impl.Underlier) {
// implLogger := underlier.GetUnderlying()
// ...
// }
// }
//
// func DoSomethingWithImpl(log logr.Logger) {
// if underlier, ok := log.GetSink().(impl.Underlier); ok {
// implLogger := underlier.GetUnderlying()
// ...
// }
// }
//
// Custom `With*` functions can be implemented by copying the complete
// Logger struct and replacing the sink in the copy:
// // WithFooBar changes the foobar parameter in the log sink and returns a
// // new logger with that modified sink. It does nothing for loggers where
// // the sink doesn't support that parameter.
// func WithFoobar(log logr.Logger, foobar int) logr.Logger {
// if foobarLogSink, ok := log.GetSink()(FoobarSink); ok {
// log = log.WithSink(foobarLogSink.WithFooBar(foobar))
// }
// return log
// }
//
// // WithFooBar changes the foobar parameter in the log sink and returns a
// // new logger with that modified sink. It does nothing for loggers where
// // the sink doesn't support that parameter.
// func WithFoobar(log logr.Logger, foobar int) logr.Logger {
// if foobarLogSink, ok := log.GetSink().(FoobarSink); ok {
// log = log.WithSink(foobarLogSink.WithFooBar(foobar))
// }
// return log
// }
//
// Don't use New to construct a new Logger with a LogSink retrieved from an
// existing Logger. Source code attribution might not work correctly and
@ -201,11 +212,14 @@ import (
)
// New returns a new Logger instance. This is primarily used by libraries
// implementing LogSink, rather than end users.
// implementing LogSink, rather than end users. Passing a nil sink will create
// a Logger which discards all log lines.
func New(sink LogSink) Logger {
logger := Logger{}
logger.setSink(sink)
sink.Init(runtimeInfo)
if sink != nil {
sink.Init(runtimeInfo)
}
return logger
}
@ -244,7 +258,13 @@ type Logger struct {
// Enabled tests whether this Logger is enabled. For example, commandline
// flags might be used to set the logging verbosity and disable some info logs.
func (l Logger) Enabled() bool {
return l.sink.Enabled(l.level)
// Some implementations of LogSink look at the caller in Enabled (e.g.
// different verbosity levels per package or file), but we only pass one
// CallDepth in (via Init). This means that all calls from Logger to the
// LogSink's Enabled, Info, and Error methods must have the same number of
// frames. In other words, Logger methods can't call other Logger methods
// which call these LogSink methods unless we do it the same in all paths.
return l.sink != nil && l.sink.Enabled(l.level)
}
// Info logs a non-error message with the given key/value pairs as context.
@ -253,8 +273,11 @@ func (l Logger) Enabled() bool {
// line. The key/value pairs can then be used to add additional variable
// information. The key/value pairs must alternate string keys and arbitrary
// values.
func (l Logger) Info(msg string, keysAndValues ...interface{}) {
if l.Enabled() {
func (l Logger) Info(msg string, keysAndValues ...any) {
if l.sink == nil {
return
}
if l.sink.Enabled(l.level) { // see comment in Enabled
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
withHelper.GetCallStackHelper()()
}
@ -272,7 +295,10 @@ func (l Logger) Info(msg string, keysAndValues ...interface{}) {
// while the err argument should be used to attach the actual error that
// triggered this log line, if present. The err parameter is optional
// and nil may be passed instead of an error instance.
func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) {
func (l Logger) Error(err error, msg string, keysAndValues ...any) {
if l.sink == nil {
return
}
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
withHelper.GetCallStackHelper()()
}
@ -284,6 +310,9 @@ func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) {
// level means a log message is less important. Negative V-levels are treated
// as 0.
func (l Logger) V(level int) Logger {
if l.sink == nil {
return l
}
if level < 0 {
level = 0
}
@ -291,9 +320,19 @@ func (l Logger) V(level int) Logger {
return l
}
// GetV returns the verbosity level of the logger. If the logger's LogSink is
// nil as in the Discard logger, this will always return 0.
func (l Logger) GetV() int {
// 0 if l.sink nil because of the if check in V above.
return l.level
}
// WithValues returns a new Logger instance with additional key/value pairs.
// See Info for documentation on how key/value pairs work.
func (l Logger) WithValues(keysAndValues ...interface{}) Logger {
func (l Logger) WithValues(keysAndValues ...any) Logger {
if l.sink == nil {
return l
}
l.setSink(l.sink.WithValues(keysAndValues...))
return l
}
@ -304,6 +343,9 @@ func (l Logger) WithValues(keysAndValues ...interface{}) Logger {
// contain only letters, digits, and hyphens (see the package documentation for
// more information).
func (l Logger) WithName(name string) Logger {
if l.sink == nil {
return l
}
l.setSink(l.sink.WithName(name))
return l
}
@ -324,6 +366,9 @@ func (l Logger) WithName(name string) Logger {
// WithCallDepth(1) because it works with implementions that support the
// CallDepthLogSink and/or CallStackHelperLogSink interfaces.
func (l Logger) WithCallDepth(depth int) Logger {
if l.sink == nil {
return l
}
if withCallDepth, ok := l.sink.(CallDepthLogSink); ok {
l.setSink(withCallDepth.WithCallDepth(depth))
}
@ -345,6 +390,9 @@ func (l Logger) WithCallDepth(depth int) Logger {
// implementation does not support either of these, the original Logger will be
// returned.
func (l Logger) WithCallStackHelper() (func(), Logger) {
if l.sink == nil {
return func() {}, l
}
var helper func()
if withCallDepth, ok := l.sink.(CallDepthLogSink); ok {
l.setSink(withCallDepth.WithCallDepth(1))
@ -357,6 +405,11 @@ func (l Logger) WithCallStackHelper() (func(), Logger) {
return helper, l
}
// IsZero returns true if this logger is an uninitialized zero value
func (l Logger) IsZero() bool {
return l.sink == nil
}
// contextKey is how we find Loggers in a context.Context.
type contextKey struct{}
@ -427,22 +480,22 @@ type LogSink interface {
// The level argument is provided for optional logging. This method will
// only be called when Enabled(level) is true. See Logger.Info for more
// details.
Info(level int, msg string, keysAndValues ...interface{})
Info(level int, msg string, keysAndValues ...any)
// Error logs an error, with the given message and key/value pairs as
// context. See Logger.Error for more details.
Error(err error, msg string, keysAndValues ...interface{})
Error(err error, msg string, keysAndValues ...any)
// WithValues returns a new LogSink with additional key/value pairs. See
// Logger.WithValues for more details.
WithValues(keysAndValues ...interface{}) LogSink
WithValues(keysAndValues ...any) LogSink
// WithName returns a new LogSink with the specified name appended. See
// Logger.WithName for more details.
WithName(name string) LogSink
}
// CallDepthLogSink represents a Logger that knows how to climb the call stack
// CallDepthLogSink represents a LogSink that knows how to climb the call stack
// to identify the original call site and can offset the depth by a specified
// number of frames. This is useful for users who have helper functions
// between the "real" call site and the actual calls to Logger methods.
@ -467,7 +520,7 @@ type CallDepthLogSink interface {
WithCallDepth(depth int) LogSink
}
// CallStackHelperLogSink represents a Logger that knows how to climb
// CallStackHelperLogSink represents a LogSink that knows how to climb
// the call stack to identify the original call site and can skip
// intermediate helper functions if they mark themselves as
// helper. Go's testing package uses that approach.
@ -506,5 +559,5 @@ type Marshaler interface {
// with exported fields
//
// It may return any value of any type.
MarshalLog() interface{}
MarshalLog() any
}

168
src/vendor/github.com/go-logr/logr/slogr/sloghandler.go generated vendored Normal file
View File

@ -0,0 +1,168 @@
//go:build go1.21
// +build go1.21
/*
Copyright 2023 The logr Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package slogr
import (
"context"
"log/slog"
"github.com/go-logr/logr"
)
type slogHandler struct {
// May be nil, in which case all logs get discarded.
sink logr.LogSink
// Non-nil if sink is non-nil and implements SlogSink.
slogSink SlogSink
// groupPrefix collects values from WithGroup calls. It gets added as
// prefix to value keys when handling a log record.
groupPrefix string
// levelBias can be set when constructing the handler to influence the
// slog.Level of log records. A positive levelBias reduces the
// slog.Level value. slog has no API to influence this value after the
// handler got created, so it can only be set indirectly through
// Logger.V.
levelBias slog.Level
}
var _ slog.Handler = &slogHandler{}
// groupSeparator is used to concatenate WithGroup names and attribute keys.
const groupSeparator = "."
// GetLevel is used for black box unit testing.
func (l *slogHandler) GetLevel() slog.Level {
return l.levelBias
}
func (l *slogHandler) Enabled(ctx context.Context, level slog.Level) bool {
return l.sink != nil && (level >= slog.LevelError || l.sink.Enabled(l.levelFromSlog(level)))
}
func (l *slogHandler) Handle(ctx context.Context, record slog.Record) error {
if l.slogSink != nil {
// Only adjust verbosity level of log entries < slog.LevelError.
if record.Level < slog.LevelError {
record.Level -= l.levelBias
}
return l.slogSink.Handle(ctx, record)
}
// No need to check for nil sink here because Handle will only be called
// when Enabled returned true.
kvList := make([]any, 0, 2*record.NumAttrs())
record.Attrs(func(attr slog.Attr) bool {
if attr.Key != "" {
kvList = append(kvList, l.addGroupPrefix(attr.Key), attr.Value.Resolve().Any())
}
return true
})
if record.Level >= slog.LevelError {
l.sinkWithCallDepth().Error(nil, record.Message, kvList...)
} else {
level := l.levelFromSlog(record.Level)
l.sinkWithCallDepth().Info(level, record.Message, kvList...)
}
return nil
}
// sinkWithCallDepth adjusts the stack unwinding so that when Error or Info
// are called by Handle, code in slog gets skipped.
//
// This offset currently (Go 1.21.0) works for calls through
// slog.New(NewSlogHandler(...)). There's no guarantee that the call
// chain won't change. Wrapping the handler will also break unwinding. It's
// still better than not adjusting at all....
//
// This cannot be done when constructing the handler because NewLogr needs
// access to the original sink without this adjustment. A second copy would
// work, but then WithAttrs would have to be called for both of them.
func (l *slogHandler) sinkWithCallDepth() logr.LogSink {
if sink, ok := l.sink.(logr.CallDepthLogSink); ok {
return sink.WithCallDepth(2)
}
return l.sink
}
func (l *slogHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
if l.sink == nil || len(attrs) == 0 {
return l
}
copy := *l
if l.slogSink != nil {
copy.slogSink = l.slogSink.WithAttrs(attrs)
copy.sink = copy.slogSink
} else {
kvList := make([]any, 0, 2*len(attrs))
for _, attr := range attrs {
if attr.Key != "" {
kvList = append(kvList, l.addGroupPrefix(attr.Key), attr.Value.Resolve().Any())
}
}
copy.sink = l.sink.WithValues(kvList...)
}
return &copy
}
func (l *slogHandler) WithGroup(name string) slog.Handler {
if l.sink == nil {
return l
}
copy := *l
if l.slogSink != nil {
copy.slogSink = l.slogSink.WithGroup(name)
copy.sink = l.slogSink
} else {
copy.groupPrefix = copy.addGroupPrefix(name)
}
return &copy
}
func (l *slogHandler) addGroupPrefix(name string) string {
if l.groupPrefix == "" {
return name
}
return l.groupPrefix + groupSeparator + name
}
// levelFromSlog adjusts the level by the logger's verbosity and negates it.
// It ensures that the result is >= 0. This is necessary because the result is
// passed to a logr.LogSink and that API did not historically document whether
// levels could be negative or what that meant.
//
// Some example usage:
// logrV0 := getMyLogger()
// logrV2 := logrV0.V(2)
// slogV2 := slog.New(slogr.NewSlogHandler(logrV2))
// slogV2.Debug("msg") // =~ logrV2.V(4) =~ logrV0.V(6)
// slogV2.Info("msg") // =~ logrV2.V(0) =~ logrV0.V(2)
// slogv2.Warn("msg") // =~ logrV2.V(-4) =~ logrV0.V(0)
func (l *slogHandler) levelFromSlog(level slog.Level) int {
result := -level
result += l.levelBias // in case the original logr.Logger had a V level
if result < 0 {
result = 0 // because logr.LogSink doesn't expect negative V levels
}
return int(result)
}

108
src/vendor/github.com/go-logr/logr/slogr/slogr.go generated vendored Normal file
View File

@ -0,0 +1,108 @@
//go:build go1.21
// +build go1.21
/*
Copyright 2023 The logr Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package slogr enables usage of a slog.Handler with logr.Logger as front-end
// API and of a logr.LogSink through the slog.Handler and thus slog.Logger
// APIs.
//
// See the README in the top-level [./logr] package for a discussion of
// interoperability.
package slogr
import (
"context"
"log/slog"
"github.com/go-logr/logr"
)
// NewLogr returns a logr.Logger which writes to the slog.Handler.
//
// The logr verbosity level is mapped to slog levels such that V(0) becomes
// slog.LevelInfo and V(4) becomes slog.LevelDebug.
func NewLogr(handler slog.Handler) logr.Logger {
if handler, ok := handler.(*slogHandler); ok {
if handler.sink == nil {
return logr.Discard()
}
return logr.New(handler.sink).V(int(handler.levelBias))
}
return logr.New(&slogSink{handler: handler})
}
// NewSlogHandler returns a slog.Handler which writes to the same sink as the logr.Logger.
//
// The returned logger writes all records with level >= slog.LevelError as
// error log entries with LogSink.Error, regardless of the verbosity level of
// the logr.Logger:
//
// logger := <some logr.Logger with 0 as verbosity level>
// slog.New(NewSlogHandler(logger.V(10))).Error(...) -> logSink.Error(...)
//
// The level of all other records gets reduced by the verbosity
// level of the logr.Logger and the result is negated. If it happens
// to be negative, then it gets replaced by zero because a LogSink
// is not expected to handled negative levels:
//
// slog.New(NewSlogHandler(logger)).Debug(...) -> logger.GetSink().Info(level=4, ...)
// slog.New(NewSlogHandler(logger)).Warning(...) -> logger.GetSink().Info(level=0, ...)
// slog.New(NewSlogHandler(logger)).Info(...) -> logger.GetSink().Info(level=0, ...)
// slog.New(NewSlogHandler(logger.V(4))).Info(...) -> logger.GetSink().Info(level=4, ...)
func NewSlogHandler(logger logr.Logger) slog.Handler {
if sink, ok := logger.GetSink().(*slogSink); ok && logger.GetV() == 0 {
return sink.handler
}
handler := &slogHandler{sink: logger.GetSink(), levelBias: slog.Level(logger.GetV())}
if slogSink, ok := handler.sink.(SlogSink); ok {
handler.slogSink = slogSink
}
return handler
}
// SlogSink is an optional interface that a LogSink can implement to support
// logging through the slog.Logger or slog.Handler APIs better. It then should
// also support special slog values like slog.Group. When used as a
// slog.Handler, the advantages are:
//
// - stack unwinding gets avoided in favor of logging the pre-recorded PC,
// as intended by slog
// - proper grouping of key/value pairs via WithGroup
// - verbosity levels > slog.LevelInfo can be recorded
// - less overhead
//
// Both APIs (logr.Logger and slog.Logger/Handler) then are supported equally
// well. Developers can pick whatever API suits them better and/or mix
// packages which use either API in the same binary with a common logging
// implementation.
//
// This interface is necessary because the type implementing the LogSink
// interface cannot also implement the slog.Handler interface due to the
// different prototype of the common Enabled method.
//
// An implementation could support both interfaces in two different types, but then
// additional interfaces would be needed to convert between those types in NewLogr
// and NewSlogHandler.
type SlogSink interface {
logr.LogSink
Handle(ctx context.Context, record slog.Record) error
WithAttrs(attrs []slog.Attr) SlogSink
WithGroup(name string) SlogSink
}

122
src/vendor/github.com/go-logr/logr/slogr/slogsink.go generated vendored Normal file
View File

@ -0,0 +1,122 @@
//go:build go1.21
// +build go1.21
/*
Copyright 2023 The logr Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package slogr
import (
"context"
"log/slog"
"runtime"
"time"
"github.com/go-logr/logr"
)
var (
_ logr.LogSink = &slogSink{}
_ logr.CallDepthLogSink = &slogSink{}
_ Underlier = &slogSink{}
)
// Underlier is implemented by the LogSink returned by NewLogr.
type Underlier interface {
// GetUnderlying returns the Handler used by the LogSink.
GetUnderlying() slog.Handler
}
const (
// nameKey is used to log the `WithName` values as an additional attribute.
nameKey = "logger"
// errKey is used to log the error parameter of Error as an additional attribute.
errKey = "err"
)
type slogSink struct {
callDepth int
name string
handler slog.Handler
}
func (l *slogSink) Init(info logr.RuntimeInfo) {
l.callDepth = info.CallDepth
}
func (l *slogSink) GetUnderlying() slog.Handler {
return l.handler
}
func (l *slogSink) WithCallDepth(depth int) logr.LogSink {
newLogger := *l
newLogger.callDepth += depth
return &newLogger
}
func (l *slogSink) Enabled(level int) bool {
return l.handler.Enabled(context.Background(), slog.Level(-level))
}
func (l *slogSink) Info(level int, msg string, kvList ...interface{}) {
l.log(nil, msg, slog.Level(-level), kvList...)
}
func (l *slogSink) Error(err error, msg string, kvList ...interface{}) {
l.log(err, msg, slog.LevelError, kvList...)
}
func (l *slogSink) log(err error, msg string, level slog.Level, kvList ...interface{}) {
var pcs [1]uintptr
// skip runtime.Callers, this function, Info/Error, and all helper functions above that.
runtime.Callers(3+l.callDepth, pcs[:])
record := slog.NewRecord(time.Now(), level, msg, pcs[0])
if l.name != "" {
record.AddAttrs(slog.String(nameKey, l.name))
}
if err != nil {
record.AddAttrs(slog.Any(errKey, err))
}
record.Add(kvList...)
l.handler.Handle(context.Background(), record)
}
func (l slogSink) WithName(name string) logr.LogSink {
if l.name != "" {
l.name = l.name + "/"
}
l.name += name
return &l
}
func (l slogSink) WithValues(kvList ...interface{}) logr.LogSink {
l.handler = l.handler.WithAttrs(kvListToAttrs(kvList...))
return &l
}
func kvListToAttrs(kvList ...interface{}) []slog.Attr {
// We don't need the record itself, only its Add method.
record := slog.NewRecord(time.Time{}, 0, "", 0)
record.Add(kvList...)
attrs := make([]slog.Attr, 0, record.NumAttrs())
record.Attrs(func(attr slog.Attr) bool {
attrs = append(attrs, attr)
return true
})
return attrs
}

View File

@ -1,15 +0,0 @@
after_success:
- bash <(curl -s https://codecov.io/bash)
go:
- 1.14.x
- 1.15.x
install:
- GO111MODULE=off go get -u gotest.tools/gotestsum
env:
- GO111MODULE=on
language: go
notifications:
slack:
secure: a5VgoiwB1G/AZqzmephPZIhEB9avMlsWSlVnM1dSAtYAwdrQHGTQxAmpOxYIoSPDhWNN5bfZmjd29++UlTwLcHSR+e0kJhH6IfDlsHj/HplNCJ9tyI0zYc7XchtdKgeMxMzBKCzgwFXGSbQGydXTliDNBo0HOzmY3cou/daMFTP60K+offcjS+3LRAYb1EroSRXZqrk1nuF/xDL3792DZUdPMiFR/L/Df6y74D6/QP4sTkTDFQitz4Wy/7jbsfj8dG6qK2zivgV6/l+w4OVjFkxVpPXogDWY10vVXNVynqxfJ7to2d1I9lNCHE2ilBCkWMIPdyJF7hjF8pKW+82yP4EzRh0vu8Xn0HT5MZpQxdRY/YMxNrWaG7SxsoEaO4q5uhgdzAqLYY3TRa7MjIK+7Ur+aqOeTXn6OKwVi0CjvZ6mIU3WUKSwiwkFZMbjRAkSb5CYwMEfGFO/z964xz83qGt6WAtBXNotqCQpTIiKtDHQeLOMfksHImCg6JLhQcWBVxamVgu0G3Pdh8Y6DyPnxraXY95+QDavbjqv7TeYT9T/FNnrkXaTTK0s4iWE5H4ACU0Qvz0wUYgfQrZv0/Hp7V17+rabUwnzYySHCy9SWX/7OV9Cfh31iMp9ZIffr76xmmThtOEqs8TrTtU6BWI3rWwvA9cXQipZTVtL0oswrGw=
script:
- gotestsum -f short-verbose -- -race -coverprofile=coverage.txt -covermode=atomic ./...

View File

@ -1,8 +1,6 @@
linters-settings:
govet:
check-shadowing: true
golint:
min-confidence: 0
gocyclo:
min-complexity: 30
maligned:
@ -12,6 +10,8 @@ linters-settings:
goconst:
min-len: 2
min-occurrences: 4
paralleltest:
ignore-missing: true
linters:
enable-all: true
disable:
@ -39,3 +39,12 @@ linters:
- nestif
- godot
- errorlint
- varcheck
- interfacer
- deadcode
- golint
- ifshort
- structcheck
- nosnakecase
- varnamelen
- exhaustruct

View File

@ -1,24 +0,0 @@
after_success:
- bash <(curl -s https://codecov.io/bash)
go:
- 1.14.x
- 1.x
install:
- go get gotest.tools/gotestsum
jobs:
include:
# include linting job, but only for latest go version and amd64 arch
- go: 1.x
arch: amd64
install:
go get github.com/golangci/golangci-lint/cmd/golangci-lint
script:
- golangci-lint run --new-from-rev master
env:
- GO111MODULE=on
language: go
notifications:
slack:
secure: OpQG/36F7DSF00HLm9WZMhyqFCYYyYTsVDObW226cWiR8PWYiNfLZiSEvIzT1Gx4dDjhigKTIqcLhG34CkL5iNXDjm9Yyo2RYhQPlK8NErNqUEXuBqn4RqYHW48VGhEhOyDd4Ei0E2FN5ZbgpvHgtpkdZ6XDi64r3Ac89isP9aPHXQTuv2Jog6b4/OKKiUTftLcTIst0p4Cp3gqOJWf1wnoj+IadWiECNVQT6zb47IYjtyw6+uV8iUjTzdKcRB6Zc6b4Dq7JAg1Zd7Jfxkql3hlKp4PNlRf9Cy7y5iA3G7MLyg3FcPX5z2kmcyPt2jOTRMBWUJ5zIQpOxizAcN8WsT3WWBL5KbuYK6k0PzujrIDLqdxGpNmjkkMfDBT9cKmZpm2FdW+oZgPFJP+oKmAo4u4KJz/vjiPTXgQlN5bmrLuRMCp+AwC5wkIohTqWZVPE2TK6ZSnMYcg/W39s+RP/9mJoyryAvPSpBOLTI+biCgaUCTOAZxNTWpMFc3tPYntc41WWkdKcooZ9JA5DwfcaVFyTGQ3YXz+HvX6G1z/gW0Q/A4dBi9mj2iE1xm7tRTT+4VQ2AXFvSEI1HJpfPgYnwAtwOD1v3Qm2EUHk9sCdtEDR4wVGEPIVn44GnwFMnGKx9JWppMPYwFu3SVDdHt+E+LOlhZUply11Aa+IVrT2KUQ=
script:
- gotestsum -f short-verbose -- -race -coverprofile=coverage.txt -covermode=atomic ./...

View File

@ -7,8 +7,8 @@ import (
)
const (
defaultHttpPort = ":80"
defaultHttpsPort = ":443"
defaultHTTPPort = ":80"
defaultHTTPSPort = ":443"
)
// Regular expressions used by the normalizations
@ -18,18 +18,24 @@ var rxDupSlashes = regexp.MustCompile(`/{2,}`)
// NormalizeURL will normalize the specified URL
// This was added to replace a previous call to the no longer maintained purell library:
// The call that was used looked like the following:
// url.Parse(purell.NormalizeURL(parsed, purell.FlagsSafe|purell.FlagRemoveDuplicateSlashes))
//
// url.Parse(purell.NormalizeURL(parsed, purell.FlagsSafe|purell.FlagRemoveDuplicateSlashes))
//
// To explain all that was included in the call above, purell.FlagsSafe was really just the following:
// - FlagLowercaseScheme
// - FlagLowercaseHost
// - FlagRemoveDefaultPort
// - FlagRemoveDuplicateSlashes (and this was mixed in with the |)
// - FlagLowercaseScheme
// - FlagLowercaseHost
// - FlagRemoveDefaultPort
// - FlagRemoveDuplicateSlashes (and this was mixed in with the |)
//
// This also normalizes the URL into its urlencoded form by removing RawPath and RawFragment.
func NormalizeURL(u *url.URL) {
lowercaseScheme(u)
lowercaseHost(u)
removeDefaultPort(u)
removeDuplicateSlashes(u)
u.RawPath = ""
u.RawFragment = ""
}
func lowercaseScheme(u *url.URL) {
@ -48,7 +54,7 @@ func removeDefaultPort(u *url.URL) {
if len(u.Host) > 0 {
scheme := strings.ToLower(u.Scheme)
u.Host = rxPort.ReplaceAllStringFunc(u.Host, func(val string) string {
if (scheme == "http" && val == defaultHttpPort) || (scheme == "https" && val == defaultHttpsPort) {
if (scheme == "http" && val == defaultHTTPPort) || (scheme == "https" && val == defaultHTTPSPort) {
return ""
}
return val

2
src/vendor/github.com/go-openapi/swag/.gitattributes generated vendored Normal file
View File

@ -0,0 +1,2 @@
# gofmt always uses LF, whereas Git uses CRLF on Windows.
*.go text eol=lf

View File

@ -37,3 +37,18 @@ linters:
- gci
- gocognit
- paralleltest
- thelper
- ifshort
- gomoddirectives
- cyclop
- forcetypeassert
- ireturn
- tagliatelle
- varnamelen
- goimports
- tenv
- golint
- exhaustruct
- nilnil
- nonamedreturns
- nosnakecase

View File

@ -1,37 +0,0 @@
after_success:
- bash <(curl -s https://codecov.io/bash)
go:
- 1.14.x
- 1.x
arch:
- amd64
jobs:
include:
# include arch ppc, but only for latest go version - skip testing for race
- go: 1.x
arch: ppc64le
install: ~
script:
- go test -v
#- go: 1.x
# arch: arm
# install: ~
# script:
# - go test -v
# include linting job, but only for latest go version and amd64 arch
- go: 1.x
arch: amd64
install:
go get github.com/golangci/golangci-lint/cmd/golangci-lint
script:
- golangci-lint run --new-from-rev master
install:
- GO111MODULE=off go get -u gotest.tools/gotestsum
language: go
notifications:
slack:
secure: QUWvCkBBK09GF7YtEvHHVt70JOkdlNBG0nIKu/5qc4/nW5HP8I2w0SEf/XR2je0eED1Qe3L/AfMCWwrEj+IUZc3l4v+ju8X8R3Lomhme0Eb0jd1MTMCuPcBT47YCj0M7RON7vXtbFfm1hFJ/jLe5+9FXz0hpXsR24PJc5ZIi/ogNwkaPqG4BmndzecpSh0vc2FJPZUD9LT0I09REY/vXR0oQAalLkW0asGD5taHZTUZq/kBpsNxaAFrLM23i4mUcf33M5fjLpvx5LRICrX/57XpBrDh2TooBU6Qj3CgoY0uPRYUmSNxbVx1czNzl2JtEpb5yjoxfVPQeg0BvQM00G8LJINISR+ohrjhkZmAqchDupAX+yFrxTtORa78CtnIL6z/aTNlgwwVD8kvL/1pFA/JWYmKDmz93mV/+6wubGzNSQCstzjkFA4/iZEKewKUoRIAi/fxyscP6L/rCpmY/4llZZvrnyTqVbt6URWpopUpH4rwYqreXAtJxJsfBJIeSmUIiDIOMGkCTvyTEW3fWGmGoqWtSHLoaWDyAIGb7azb+KvfpWtEcoPFWfSWU+LGee0A/YsUhBl7ADB9A0CJEuR8q4BPpKpfLwPKSiKSAXL7zDkyjExyhtgqbSl2jS+rKIHOZNL8JkCcTP2MKMVd563C5rC5FMKqu3S9m2b6380E=
script:
- gotestsum -f short-verbose -- -race -coverprofile=coverage.txt -covermode=atomic ./...

View File

@ -17,16 +17,15 @@ Package swag contains a bunch of helper functions for go-openapi and go-swagger
You may also use it standalone for your projects.
* convert between value and pointers for builtin types
* convert from string to builtin types (wraps strconv)
* fast json concatenation
* search in path
* load from file or http
* name mangling
- convert between value and pointers for builtin types
- convert from string to builtin types (wraps strconv)
- fast json concatenation
- search in path
- load from file or http
- name mangling
This repo has only few dependencies outside of the standard library:
* YAML utilities depend on gopkg.in/yaml.v2
- YAML utilities depend on gopkg.in/yaml.v2
*/
package swag

33
src/vendor/github.com/go-openapi/swag/file.go generated vendored Normal file
View File

@ -0,0 +1,33 @@
// Copyright 2015 go-swagger maintainers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package swag
import "mime/multipart"
// File represents an uploaded file.
type File struct {
Data multipart.File
Header *multipart.FileHeader
}
// Read bytes from the file
func (f *File) Read(p []byte) (n int, err error) {
return f.Data.Read(p)
}
// Close the file
func (f *File) Close() error {
return f.Data.Close()
}

View File

@ -16,10 +16,11 @@ package swag
import (
"fmt"
"io/ioutil"
"io"
"log"
"net/http"
"net/url"
"os"
"path/filepath"
"runtime"
"strings"
@ -40,13 +41,13 @@ var LoadHTTPCustomHeaders = map[string]string{}
// LoadFromFileOrHTTP loads the bytes from a file or a remote http server based on the path passed in
func LoadFromFileOrHTTP(path string) ([]byte, error) {
return LoadStrategy(path, ioutil.ReadFile, loadHTTPBytes(LoadHTTPTimeout))(path)
return LoadStrategy(path, os.ReadFile, loadHTTPBytes(LoadHTTPTimeout))(path)
}
// LoadFromFileOrHTTPWithTimeout loads the bytes from a file or a remote http server based on the path passed in
// timeout arg allows for per request overriding of the request timeout
func LoadFromFileOrHTTPWithTimeout(path string, timeout time.Duration) ([]byte, error) {
return LoadStrategy(path, ioutil.ReadFile, loadHTTPBytes(timeout))(path)
return LoadStrategy(path, os.ReadFile, loadHTTPBytes(timeout))(path)
}
// LoadStrategy returns a loader function for a given path or uri
@ -86,7 +87,7 @@ func LoadStrategy(path string, local, remote func(string) ([]byte, error)) func(
func loadHTTPBytes(timeout time.Duration) func(path string) ([]byte, error) {
return func(path string) ([]byte, error) {
client := &http.Client{Timeout: timeout}
req, err := http.NewRequest("GET", path, nil) // nolint: noctx
req, err := http.NewRequest(http.MethodGet, path, nil) //nolint:noctx
if err != nil {
return nil, err
}
@ -115,6 +116,6 @@ func loadHTTPBytes(timeout time.Duration) func(path string) ([]byte, error) {
return nil, fmt.Errorf("could not access document at %q [%s] ", path, resp.Status)
}
return ioutil.ReadAll(resp.Body)
return io.ReadAll(resp.Body)
}
}

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build go1.8
// +build go1.8
package swag

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build go1.9
// +build go1.9
package swag

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !go1.8
// +build !go1.8
package swag

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !go1.9
// +build !go1.9
package swag

View File

@ -99,10 +99,11 @@ const (
)
// JoinByFormat joins a string array by a known format (e.g. swagger's collectionFormat attribute):
// ssv: space separated value
// tsv: tab separated value
// pipes: pipe (|) separated value
// csv: comma separated value (default)
//
// ssv: space separated value
// tsv: tab separated value
// pipes: pipe (|) separated value
// csv: comma separated value (default)
func JoinByFormat(data []string, format string) []string {
if len(data) == 0 {
return data
@ -124,11 +125,11 @@ func JoinByFormat(data []string, format string) []string {
}
// SplitByFormat splits a string by a known format:
// ssv: space separated value
// tsv: tab separated value
// pipes: pipe (|) separated value
// csv: comma separated value (default)
//
// ssv: space separated value
// tsv: tab separated value
// pipes: pipe (|) separated value
// csv: comma separated value (default)
func SplitByFormat(data, format string) []string {
if data == "" {
return nil

View File

@ -22,7 +22,7 @@ import (
"github.com/mailru/easyjson/jlexer"
"github.com/mailru/easyjson/jwriter"
yaml "gopkg.in/yaml.v2"
yaml "gopkg.in/yaml.v3"
)
// YAMLMatcher matches yaml
@ -43,16 +43,126 @@ func YAMLToJSON(data interface{}) (json.RawMessage, error) {
// BytesToYAMLDoc converts a byte slice into a YAML document
func BytesToYAMLDoc(data []byte) (interface{}, error) {
var canary map[interface{}]interface{} // validate this is an object and not a different type
if err := yaml.Unmarshal(data, &canary); err != nil {
return nil, err
}
var document yaml.MapSlice // preserve order that is present in the document
var document yaml.Node // preserve order that is present in the document
if err := yaml.Unmarshal(data, &document); err != nil {
return nil, err
}
return document, nil
if document.Kind != yaml.DocumentNode || len(document.Content) != 1 || document.Content[0].Kind != yaml.MappingNode {
return nil, fmt.Errorf("only YAML documents that are objects are supported")
}
return &document, nil
}
func yamlNode(root *yaml.Node) (interface{}, error) {
switch root.Kind {
case yaml.DocumentNode:
return yamlDocument(root)
case yaml.SequenceNode:
return yamlSequence(root)
case yaml.MappingNode:
return yamlMapping(root)
case yaml.ScalarNode:
return yamlScalar(root)
case yaml.AliasNode:
return yamlNode(root.Alias)
default:
return nil, fmt.Errorf("unsupported YAML node type: %v", root.Kind)
}
}
func yamlDocument(node *yaml.Node) (interface{}, error) {
if len(node.Content) != 1 {
return nil, fmt.Errorf("unexpected YAML Document node content length: %d", len(node.Content))
}
return yamlNode(node.Content[0])
}
func yamlMapping(node *yaml.Node) (interface{}, error) {
m := make(JSONMapSlice, len(node.Content)/2)
var j int
for i := 0; i < len(node.Content); i += 2 {
var nmi JSONMapItem
k, err := yamlStringScalarC(node.Content[i])
if err != nil {
return nil, fmt.Errorf("unable to decode YAML map key: %w", err)
}
nmi.Key = k
v, err := yamlNode(node.Content[i+1])
if err != nil {
return nil, fmt.Errorf("unable to process YAML map value for key %q: %w", k, err)
}
nmi.Value = v
m[j] = nmi
j++
}
return m, nil
}
func yamlSequence(node *yaml.Node) (interface{}, error) {
s := make([]interface{}, 0)
for i := 0; i < len(node.Content); i++ {
v, err := yamlNode(node.Content[i])
if err != nil {
return nil, fmt.Errorf("unable to decode YAML sequence value: %w", err)
}
s = append(s, v)
}
return s, nil
}
const ( // See https://yaml.org/type/
yamlStringScalar = "tag:yaml.org,2002:str"
yamlIntScalar = "tag:yaml.org,2002:int"
yamlBoolScalar = "tag:yaml.org,2002:bool"
yamlFloatScalar = "tag:yaml.org,2002:float"
yamlTimestamp = "tag:yaml.org,2002:timestamp"
yamlNull = "tag:yaml.org,2002:null"
)
func yamlScalar(node *yaml.Node) (interface{}, error) {
switch node.LongTag() {
case yamlStringScalar:
return node.Value, nil
case yamlBoolScalar:
b, err := strconv.ParseBool(node.Value)
if err != nil {
return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting bool content: %w", node.Value, err)
}
return b, nil
case yamlIntScalar:
i, err := strconv.ParseInt(node.Value, 10, 64)
if err != nil {
return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting integer content: %w", node.Value, err)
}
return i, nil
case yamlFloatScalar:
f, err := strconv.ParseFloat(node.Value, 64)
if err != nil {
return nil, fmt.Errorf("unable to process scalar node. Got %q. Expecting float content: %w", node.Value, err)
}
return f, nil
case yamlTimestamp:
return node.Value, nil
case yamlNull:
return nil, nil
default:
return nil, fmt.Errorf("YAML tag %q is not supported", node.LongTag())
}
}
func yamlStringScalarC(node *yaml.Node) (string, error) {
if node.Kind != yaml.ScalarNode {
return "", fmt.Errorf("expecting a string scalar but got %q", node.Kind)
}
switch node.LongTag() {
case yamlStringScalar, yamlIntScalar, yamlFloatScalar:
return node.Value, nil
default:
return "", fmt.Errorf("YAML tag %q is not supported as map key", node.LongTag())
}
}
// JSONMapSlice represent a JSON object, with the order of keys maintained
@ -105,6 +215,113 @@ func (s *JSONMapSlice) UnmarshalEasyJSON(in *jlexer.Lexer) {
*s = result
}
func (s JSONMapSlice) MarshalYAML() (interface{}, error) {
var n yaml.Node
n.Kind = yaml.DocumentNode
var nodes []*yaml.Node
for _, item := range s {
nn, err := json2yaml(item.Value)
if err != nil {
return nil, err
}
ns := []*yaml.Node{
{
Kind: yaml.ScalarNode,
Tag: yamlStringScalar,
Value: item.Key,
},
nn,
}
nodes = append(nodes, ns...)
}
n.Content = []*yaml.Node{
{
Kind: yaml.MappingNode,
Content: nodes,
},
}
return yaml.Marshal(&n)
}
func json2yaml(item interface{}) (*yaml.Node, error) {
switch val := item.(type) {
case JSONMapSlice:
var n yaml.Node
n.Kind = yaml.MappingNode
for i := range val {
childNode, err := json2yaml(&val[i].Value)
if err != nil {
return nil, err
}
n.Content = append(n.Content, &yaml.Node{
Kind: yaml.ScalarNode,
Tag: yamlStringScalar,
Value: val[i].Key,
}, childNode)
}
return &n, nil
case map[string]interface{}:
var n yaml.Node
n.Kind = yaml.MappingNode
for k, v := range val {
childNode, err := json2yaml(v)
if err != nil {
return nil, err
}
n.Content = append(n.Content, &yaml.Node{
Kind: yaml.ScalarNode,
Tag: yamlStringScalar,
Value: k,
}, childNode)
}
return &n, nil
case []interface{}:
var n yaml.Node
n.Kind = yaml.SequenceNode
for i := range val {
childNode, err := json2yaml(val[i])
if err != nil {
return nil, err
}
n.Content = append(n.Content, childNode)
}
return &n, nil
case string:
return &yaml.Node{
Kind: yaml.ScalarNode,
Tag: yamlStringScalar,
Value: val,
}, nil
case float64:
return &yaml.Node{
Kind: yaml.ScalarNode,
Tag: yamlFloatScalar,
Value: strconv.FormatFloat(val, 'f', -1, 64),
}, nil
case int64:
return &yaml.Node{
Kind: yaml.ScalarNode,
Tag: yamlIntScalar,
Value: strconv.FormatInt(val, 10),
}, nil
case uint64:
return &yaml.Node{
Kind: yaml.ScalarNode,
Tag: yamlIntScalar,
Value: strconv.FormatUint(val, 10),
}, nil
case bool:
return &yaml.Node{
Kind: yaml.ScalarNode,
Tag: yamlBoolScalar,
Value: strconv.FormatBool(val),
}, nil
}
return nil, nil
}
// JSONMapItem represents the value of a key in a JSON object held by JSONMapSlice
type JSONMapItem struct {
Key string
@ -173,23 +390,10 @@ func transformData(input interface{}) (out interface{}, err error) {
}
switch in := input.(type) {
case yaml.MapSlice:
o := make(JSONMapSlice, len(in))
for i, mi := range in {
var nmi JSONMapItem
if nmi.Key, err = format(mi.Key); err != nil {
return nil, err
}
v, ert := transformData(mi.Value)
if ert != nil {
return nil, ert
}
nmi.Value = v
o[i] = nmi
}
return o, nil
case yaml.Node:
return yamlNode(&in)
case *yaml.Node:
return yamlNode(in)
case map[interface{}]interface{}:
o := make(JSONMapSlice, 0, len(in))
for ke, va := range in {

View File

@ -386,8 +386,14 @@ func (u *Unmarshaler) unmarshalMessage(m protoreflect.Message, in []byte) error
}
func isSingularWellKnownValue(fd protoreflect.FieldDescriptor) bool {
if fd.Cardinality() == protoreflect.Repeated {
return false
}
if md := fd.Message(); md != nil {
return md.FullName() == "google.protobuf.Value" && fd.Cardinality() != protoreflect.Repeated
return md.FullName() == "google.protobuf.Value"
}
if ed := fd.Enum(); ed != nil {
return ed.FullName() == "google.protobuf.NullValue"
}
return false
}

View File

@ -401,6 +401,7 @@ func (r *Lexer) scanToken() {
// consume resets the current token to allow scanning the next one.
func (r *Lexer) consume() {
r.token.kind = tokenUndef
r.token.byteValueCloned = false
r.token.delimValue = 0
}
@ -528,6 +529,7 @@ func (r *Lexer) Skip() {
func (r *Lexer) SkipRecursive() {
r.scanToken()
var start, end byte
startPos := r.start
switch r.token.delimValue {
case '{':
@ -553,6 +555,14 @@ func (r *Lexer) SkipRecursive() {
level--
if level == 0 {
r.pos += i + 1
if !json.Valid(r.Data[startPos:r.pos]) {
r.pos = len(r.Data)
r.fatalError = &LexerError{
Reason: "skipped array/object json value is invalid",
Offset: r.pos,
Data: string(r.Data[r.pos:]),
}
}
return
}
case c == '\\' && inQuotes:
@ -702,6 +712,10 @@ func (r *Lexer) Bytes() []byte {
r.errInvalidToken("string")
return nil
}
if err := r.unescapeStringToken(); err != nil {
r.errInvalidToken("string")
return nil
}
ret := make([]byte, base64.StdEncoding.DecodedLen(len(r.token.byteValue)))
n, err := base64.StdEncoding.Decode(ret, r.token.byteValue)
if err != nil {

View File

@ -59,13 +59,4 @@ const (
// AnnotationBaseImageName is the annotation key for the image reference of the image's base image.
AnnotationBaseImageName = "org.opencontainers.image.base.name"
// AnnotationArtifactCreated is the annotation key for the date and time on which the artifact was built, conforming to RFC 3339.
AnnotationArtifactCreated = "org.opencontainers.artifact.created"
// AnnotationArtifactDescription is the annotation key for the human readable description for the artifact.
AnnotationArtifactDescription = "org.opencontainers.artifact.description"
// AnnotationReferrersFiltersApplied is the annotation key for the comma separated list of filters applied by the registry in the referrers listing.
AnnotationReferrersFiltersApplied = "org.opencontainers.referrers.filtersApplied"
)

View File

@ -1,34 +0,0 @@
// Copyright 2022 The Linux Foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1
// Artifact describes an artifact manifest.
// This structure provides `application/vnd.oci.artifact.manifest.v1+json` mediatype when marshalled to JSON.
type Artifact struct {
// MediaType is the media type of the object this schema refers to.
MediaType string `json:"mediaType"`
// ArtifactType is the IANA media type of the artifact this schema refers to.
ArtifactType string `json:"artifactType"`
// Blobs is a collection of blobs referenced by this manifest.
Blobs []Descriptor `json:"blobs,omitempty"`
// Subject (reference) is an optional link from the artifact to another manifest forming an association between the artifact and the other manifest.
Subject *Descriptor `json:"subject,omitempty"`
// Annotations contains arbitrary metadata for the artifact manifest.
Annotations map[string]string `json:"annotations,omitempty"`
}

View File

@ -49,13 +49,15 @@ type ImageConfig struct {
// StopSignal contains the system call signal that will be sent to the container to exit.
StopSignal string `json:"StopSignal,omitempty"`
// ArgsEscaped `[Deprecated]` - This field is present only for legacy
// compatibility with Docker and should not be used by new image builders.
// It is used by Docker for Windows images to indicate that the `Entrypoint`
// or `Cmd` or both, contains only a single element array, that is a
// pre-escaped, and combined into a single string `CommandLine`. If `true`
// the value in `Entrypoint` or `Cmd` should be used as-is to avoid double
// escaping.
// ArgsEscaped
//
// Deprecated: This field is present only for legacy compatibility with
// Docker and should not be used by new image builders. It is used by Docker
// for Windows images to indicate that the `Entrypoint` or `Cmd` or both,
// contains only a single element array, that is a pre-escaped, and combined
// into a single string `CommandLine`. If `true` the value in `Entrypoint` or
// `Cmd` should be used as-is to avoid double escaping.
// https://github.com/opencontainers/image-spec/pull/892
ArgsEscaped bool `json:"ArgsEscaped,omitempty"`
}
@ -95,22 +97,8 @@ type Image struct {
// Author defines the name and/or email address of the person or entity which created and is responsible for maintaining the image.
Author string `json:"author,omitempty"`
// Architecture is the CPU architecture which the binaries in this image are built to run on.
Architecture string `json:"architecture"`
// Variant is the variant of the specified CPU architecture which image binaries are intended to run on.
Variant string `json:"variant,omitempty"`
// OS is the name of the operating system which the image is built to run on.
OS string `json:"os"`
// OSVersion is an optional field specifying the operating system
// version, for example on Windows `10.0.14393.1066`.
OSVersion string `json:"os.version,omitempty"`
// OSFeatures is an optional field specifying an array of strings,
// each listing a required OS feature (for example on Windows `win32k`).
OSFeatures []string `json:"os.features,omitempty"`
// Platform describes the platform which the image in the manifest runs on.
Platform
// Config defines the execution parameters which should be used as a base when running a container using the image.
Config ImageConfig `json:"config,omitempty"`

View File

@ -21,7 +21,7 @@ import digest "github.com/opencontainers/go-digest"
// when marshalled to JSON.
type Descriptor struct {
// MediaType is the media type of the object this schema refers to.
MediaType string `json:"mediaType,omitempty"`
MediaType string `json:"mediaType"`
// Digest is the digest of the targeted content.
Digest digest.Digest `json:"digest"`
@ -52,7 +52,7 @@ type Descriptor struct {
// Platform describes the platform which the image in the manifest runs on.
type Platform struct {
// Architecture field specifies the CPU architecture, for example
// `amd64` or `ppc64`.
// `amd64` or `ppc64le`.
Architecture string `json:"architecture"`
// OS specifies the operating system, for example `linux` or `windows`.
@ -70,3 +70,11 @@ type Platform struct {
// example `v7` to specify ARMv7 when architecture is `arm`.
Variant string `json:"variant,omitempty"`
}
// DescriptorEmptyJSON is the descriptor of a blob with content of `{}`.
var DescriptorEmptyJSON = Descriptor{
MediaType: MediaTypeEmptyJSON,
Digest: `sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a`,
Size: 2,
Data: []byte(`{}`),
}

View File

@ -24,9 +24,15 @@ type Index struct {
// MediaType specifies the type of this document data structure e.g. `application/vnd.oci.image.index.v1+json`
MediaType string `json:"mediaType,omitempty"`
// ArtifactType specifies the IANA media type of artifact when the manifest is used for an artifact.
ArtifactType string `json:"artifactType,omitempty"`
// Manifests references platform specific manifests.
Manifests []Descriptor `json:"manifests"`
// Subject is an optional link from the image manifest to another manifest forming an association between the image manifest and the other manifest.
Subject *Descriptor `json:"subject,omitempty"`
// Annotations contains arbitrary metadata for the image index.
Annotations map[string]string `json:"annotations,omitempty"`
}

View File

@ -15,10 +15,14 @@
package v1
const (
// ImageLayoutFile is the file name of oci image layout file
// ImageLayoutFile is the file name containing ImageLayout in an OCI Image Layout
ImageLayoutFile = "oci-layout"
// ImageLayoutVersion is the version of ImageLayout
ImageLayoutVersion = "1.0.0"
// ImageIndexFile is the file name of the entry point for references and descriptors in an OCI Image Layout
ImageIndexFile = "index.json"
// ImageBlobsDir is the directory name containing content addressable blobs in an OCI Image Layout
ImageBlobsDir = "blobs"
)
// ImageLayout is the structure in the "oci-layout" file, found in the root

View File

@ -23,6 +23,9 @@ type Manifest struct {
// MediaType specifies the type of this document data structure e.g. `application/vnd.oci.image.manifest.v1+json`
MediaType string `json:"mediaType,omitempty"`
// ArtifactType specifies the IANA media type of artifact when the manifest is used for an artifact.
ArtifactType string `json:"artifactType,omitempty"`
// Config references a configuration object for a container, by digest.
// The referenced configuration object is a JSON blob that the runtime uses to set up the container.
Config Descriptor `json:"config"`

View File

@ -40,21 +40,36 @@ const (
// MediaTypeImageLayerNonDistributable is the media type for layers referenced by
// the manifest but with distribution restrictions.
//
// Deprecated: Non-distributable layers are deprecated, and not recommended
// for future use. Implementations SHOULD NOT produce new non-distributable
// layers.
// https://github.com/opencontainers/image-spec/pull/965
MediaTypeImageLayerNonDistributable = "application/vnd.oci.image.layer.nondistributable.v1.tar"
// MediaTypeImageLayerNonDistributableGzip is the media type for
// gzipped layers referenced by the manifest but with distribution
// restrictions.
//
// Deprecated: Non-distributable layers are deprecated, and not recommended
// for future use. Implementations SHOULD NOT produce new non-distributable
// layers.
// https://github.com/opencontainers/image-spec/pull/965
MediaTypeImageLayerNonDistributableGzip = "application/vnd.oci.image.layer.nondistributable.v1.tar+gzip"
// MediaTypeImageLayerNonDistributableZstd is the media type for zstd
// compressed layers referenced by the manifest but with distribution
// restrictions.
//
// Deprecated: Non-distributable layers are deprecated, and not recommended
// for future use. Implementations SHOULD NOT produce new non-distributable
// layers.
// https://github.com/opencontainers/image-spec/pull/965
MediaTypeImageLayerNonDistributableZstd = "application/vnd.oci.image.layer.nondistributable.v1.tar+zstd"
// MediaTypeImageConfig specifies the media type for the image configuration.
MediaTypeImageConfig = "application/vnd.oci.image.config.v1+json"
// MediaTypeArtifactManifest specifies the media type for a content descriptor.
MediaTypeArtifactManifest = "application/vnd.oci.artifact.manifest.v1+json"
// MediaTypeEmptyJSON specifies the media type for an unused blob containing the value `{}`
MediaTypeEmptyJSON = "application/vnd.oci.empty.v1+json"
)

View File

@ -25,7 +25,7 @@ const (
VersionPatch = 0
// VersionDev indicates development branch. Releases will be empty string.
VersionDev = "-dev"
VersionDev = "-rc.5"
)
// Version is the specification version that the package types support.

View File

@ -59,6 +59,18 @@ type ExemplarAdder interface {
// CounterOpts is an alias for Opts. See there for doc comments.
type CounterOpts Opts
// CounterVecOpts bundles the options to create a CounterVec metric.
// It is mandatory to set CounterOpts, see there for mandatory fields. VariableLabels
// is optional and can safely be left to its default value.
type CounterVecOpts struct {
CounterOpts
// VariableLabels are used to partition the metric vector by the given set
// of labels. Each label value will be constrained with the optional Contraint
// function, if provided.
VariableLabels ConstrainableLabels
}
// NewCounter creates a new Counter based on the provided CounterOpts.
//
// The returned implementation also implements ExemplarAdder. It is safe to
@ -174,16 +186,24 @@ type CounterVec struct {
// NewCounterVec creates a new CounterVec based on the provided CounterOpts and
// partitioned by the given label names.
func NewCounterVec(opts CounterOpts, labelNames []string) *CounterVec {
desc := NewDesc(
return V2.NewCounterVec(CounterVecOpts{
CounterOpts: opts,
VariableLabels: UnconstrainedLabels(labelNames),
})
}
// NewCounterVec creates a new CounterVec based on the provided CounterVecOpts.
func (v2) NewCounterVec(opts CounterVecOpts) *CounterVec {
desc := V2.NewDesc(
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
opts.Help,
labelNames,
opts.VariableLabels,
opts.ConstLabels,
)
return &CounterVec{
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
if len(lvs) != len(desc.variableLabels) {
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.labelNames(), lvs))
}
result := &counter{desc: desc, labelPairs: MakeLabelPairs(desc, lvs), now: time.Now}
result.init(result) // Init self-collection.

View File

@ -14,20 +14,16 @@
package prometheus
import (
"errors"
"fmt"
"sort"
"strings"
"github.com/cespare/xxhash/v2"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/model"
"google.golang.org/protobuf/proto"
"github.com/prometheus/client_golang/prometheus/internal"
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
"github.com/prometheus/common/model"
dto "github.com/prometheus/client_model/go"
)
// Desc is the descriptor used by every Prometheus Metric. It is essentially
@ -54,9 +50,9 @@ type Desc struct {
// constLabelPairs contains precalculated DTO label pairs based on
// the constant labels.
constLabelPairs []*dto.LabelPair
// variableLabels contains names of labels for which the metric
// maintains variable values.
variableLabels []string
// variableLabels contains names of labels and normalization function for
// which the metric maintains variable values.
variableLabels ConstrainedLabels
// id is a hash of the values of the ConstLabels and fqName. This
// must be unique among all registered descriptors and can therefore be
// used as an identifier of the descriptor.
@ -80,10 +76,24 @@ type Desc struct {
// For constLabels, the label values are constant. Therefore, they are fully
// specified in the Desc. See the Collector example for a usage pattern.
func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *Desc {
return V2.NewDesc(fqName, help, UnconstrainedLabels(variableLabels), constLabels)
}
// NewDesc allocates and initializes a new Desc. Errors are recorded in the Desc
// and will be reported on registration time. variableLabels and constLabels can
// be nil if no such labels should be set. fqName must not be empty.
//
// variableLabels only contain the label names and normalization functions. Their
// label values are variable and therefore not part of the Desc. (They are managed
// within the Metric.)
//
// For constLabels, the label values are constant. Therefore, they are fully
// specified in the Desc. See the Collector example for a usage pattern.
func (v2) NewDesc(fqName, help string, variableLabels ConstrainableLabels, constLabels Labels) *Desc {
d := &Desc{
fqName: fqName,
help: help,
variableLabels: variableLabels,
variableLabels: variableLabels.constrainedLabels(),
}
if !model.IsValidMetricName(model.LabelValue(fqName)) {
d.err = fmt.Errorf("%q is not a valid metric name", fqName)
@ -93,7 +103,7 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *
// their sorted label names) plus the fqName (at position 0).
labelValues := make([]string, 1, len(constLabels)+1)
labelValues[0] = fqName
labelNames := make([]string, 0, len(constLabels)+len(variableLabels))
labelNames := make([]string, 0, len(constLabels)+len(d.variableLabels))
labelNameSet := map[string]struct{}{}
// First add only the const label names and sort them...
for labelName := range constLabels {
@ -118,16 +128,16 @@ func NewDesc(fqName, help string, variableLabels []string, constLabels Labels) *
// Now add the variable label names, but prefix them with something that
// cannot be in a regular label name. That prevents matching the label
// dimension with a different mix between preset and variable labels.
for _, labelName := range variableLabels {
if !checkLabelName(labelName) {
d.err = fmt.Errorf("%q is not a valid label name for metric %q", labelName, fqName)
for _, label := range d.variableLabels {
if !checkLabelName(label.Name) {
d.err = fmt.Errorf("%q is not a valid label name for metric %q", label.Name, fqName)
return d
}
labelNames = append(labelNames, "$"+labelName)
labelNameSet[labelName] = struct{}{}
labelNames = append(labelNames, "$"+label.Name)
labelNameSet[label.Name] = struct{}{}
}
if len(labelNames) != len(labelNameSet) {
d.err = errors.New("duplicate label names")
d.err = fmt.Errorf("duplicate label names in constant and variable labels for metric %q", fqName)
return d
}

View File

@ -37,35 +37,35 @@
//
// type metrics struct {
// cpuTemp prometheus.Gauge
// hdFailures *prometheus.CounterVec
// hdFailures *prometheus.CounterVec
// }
//
// func NewMetrics(reg prometheus.Registerer) *metrics {
// m := &metrics{
// cpuTemp: prometheus.NewGauge(prometheus.GaugeOpts{
// Name: "cpu_temperature_celsius",
// Help: "Current temperature of the CPU.",
// }),
// hdFailures: prometheus.NewCounterVec(
// prometheus.CounterOpts{
// Name: "hd_errors_total",
// Help: "Number of hard-disk errors.",
// },
// []string{"device"},
// ),
// }
// reg.MustRegister(m.cpuTemp)
// reg.MustRegister(m.hdFailures)
// return m
// m := &metrics{
// cpuTemp: prometheus.NewGauge(prometheus.GaugeOpts{
// Name: "cpu_temperature_celsius",
// Help: "Current temperature of the CPU.",
// }),
// hdFailures: prometheus.NewCounterVec(
// prometheus.CounterOpts{
// Name: "hd_errors_total",
// Help: "Number of hard-disk errors.",
// },
// []string{"device"},
// ),
// }
// reg.MustRegister(m.cpuTemp)
// reg.MustRegister(m.hdFailures)
// return m
// }
//
// func main() {
// // Create a non-global registry.
// reg := prometheus.NewRegistry()
// // Create a non-global registry.
// reg := prometheus.NewRegistry()
//
// // Create new metrics and register them using the custom registry.
// m := NewMetrics(reg)
// // Set values for the new created metrics.
// // Create new metrics and register them using the custom registry.
// m := NewMetrics(reg)
// // Set values for the new created metrics.
// m.cpuTemp.Set(65.3)
// m.hdFailures.With(prometheus.Labels{"device":"/dev/sda"}).Inc()
//

View File

@ -55,6 +55,18 @@ type Gauge interface {
// GaugeOpts is an alias for Opts. See there for doc comments.
type GaugeOpts Opts
// GaugeVecOpts bundles the options to create a GaugeVec metric.
// It is mandatory to set GaugeOpts, see there for mandatory fields. VariableLabels
// is optional and can safely be left to its default value.
type GaugeVecOpts struct {
GaugeOpts
// VariableLabels are used to partition the metric vector by the given set
// of labels. Each label value will be constrained with the optional Contraint
// function, if provided.
VariableLabels ConstrainableLabels
}
// NewGauge creates a new Gauge based on the provided GaugeOpts.
//
// The returned implementation is optimized for a fast Set method. If you have a
@ -138,16 +150,24 @@ type GaugeVec struct {
// NewGaugeVec creates a new GaugeVec based on the provided GaugeOpts and
// partitioned by the given label names.
func NewGaugeVec(opts GaugeOpts, labelNames []string) *GaugeVec {
desc := NewDesc(
return V2.NewGaugeVec(GaugeVecOpts{
GaugeOpts: opts,
VariableLabels: UnconstrainedLabels(labelNames),
})
}
// NewGaugeVec creates a new GaugeVec based on the provided GaugeVecOpts.
func (v2) NewGaugeVec(opts GaugeVecOpts) *GaugeVec {
desc := V2.NewDesc(
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
opts.Help,
labelNames,
opts.VariableLabels,
opts.ConstLabels,
)
return &GaugeVec{
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
if len(lvs) != len(desc.variableLabels) {
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, lvs))
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.labelNames(), lvs))
}
result := &gauge{desc: desc, labelPairs: MakeLabelPairs(desc, lvs)}
result.init(result) // Init self-collection.

View File

@ -23,11 +23,10 @@ import (
"strings"
"sync"
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/client_golang/prometheus/internal"
dto "github.com/prometheus/client_model/go"
"google.golang.org/protobuf/proto"
)
const (

View File

@ -22,10 +22,9 @@ import (
"sync/atomic"
"time"
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
dto "github.com/prometheus/client_model/go"
"google.golang.org/protobuf/proto"
)
// nativeHistogramBounds for the frac of observed values. Only relevant for
@ -402,7 +401,7 @@ type HistogramOpts struct {
// Histogram by a Prometheus server with that feature enabled (requires
// Prometheus v2.40+). Sparse buckets are exponential buckets covering
// the whole float64 range (with the exception of the “zero” bucket, see
// SparseBucketsZeroThreshold below). From any one bucket to the next,
// NativeHistogramZeroThreshold below). From any one bucket to the next,
// the width of the bucket grows by a constant
// factor. NativeHistogramBucketFactor provides an upper bound for this
// factor (exception see below). The smaller
@ -433,7 +432,7 @@ type HistogramOpts struct {
// bucket. For best results, this should be close to a bucket
// boundary. This is usually the case if picking a power of two. If
// NativeHistogramZeroThreshold is left at zero,
// DefSparseBucketsZeroThreshold is used as the threshold. To configure
// DefNativeHistogramZeroThreshold is used as the threshold. To configure
// a zero bucket with an actual threshold of zero (i.e. only
// observations of precisely zero will go into the zero bucket), set
// NativeHistogramZeroThreshold to the NativeHistogramZeroThresholdZero
@ -469,6 +468,18 @@ type HistogramOpts struct {
NativeHistogramMaxZeroThreshold float64
}
// HistogramVecOpts bundles the options to create a HistogramVec metric.
// It is mandatory to set HistogramOpts, see there for mandatory fields. VariableLabels
// is optional and can safely be left to its default value.
type HistogramVecOpts struct {
HistogramOpts
// VariableLabels are used to partition the metric vector by the given set
// of labels. Each label value will be constrained with the optional Contraint
// function, if provided.
VariableLabels ConstrainableLabels
}
// NewHistogram creates a new Histogram based on the provided HistogramOpts. It
// panics if the buckets in HistogramOpts are not in strictly increasing order.
//
@ -489,11 +500,11 @@ func NewHistogram(opts HistogramOpts) Histogram {
func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogram {
if len(desc.variableLabels) != len(labelValues) {
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, labelValues))
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.labelNames(), labelValues))
}
for _, n := range desc.variableLabels {
if n == bucketLabel {
if n.Name == bucketLabel {
panic(errBucketLabelNotAllowed)
}
}
@ -544,16 +555,12 @@ func newHistogram(desc *Desc, opts HistogramOpts, labelValues ...string) Histogr
}
// Finally we know the final length of h.upperBounds and can make buckets
// for both counts as well as exemplars:
h.counts[0] = &histogramCounts{
buckets: make([]uint64, len(h.upperBounds)),
nativeHistogramZeroThresholdBits: math.Float64bits(h.nativeHistogramZeroThreshold),
nativeHistogramSchema: h.nativeHistogramSchema,
}
h.counts[1] = &histogramCounts{
buckets: make([]uint64, len(h.upperBounds)),
nativeHistogramZeroThresholdBits: math.Float64bits(h.nativeHistogramZeroThreshold),
nativeHistogramSchema: h.nativeHistogramSchema,
}
h.counts[0] = &histogramCounts{buckets: make([]uint64, len(h.upperBounds))}
atomic.StoreUint64(&h.counts[0].nativeHistogramZeroThresholdBits, math.Float64bits(h.nativeHistogramZeroThreshold))
atomic.StoreInt32(&h.counts[0].nativeHistogramSchema, h.nativeHistogramSchema)
h.counts[1] = &histogramCounts{buckets: make([]uint64, len(h.upperBounds))}
atomic.StoreUint64(&h.counts[1].nativeHistogramZeroThresholdBits, math.Float64bits(h.nativeHistogramZeroThreshold))
atomic.StoreInt32(&h.counts[1].nativeHistogramSchema, h.nativeHistogramSchema)
h.exemplars = make([]atomic.Value, len(h.upperBounds)+1)
h.init(h) // Init self-collection.
@ -632,8 +639,8 @@ func (hc *histogramCounts) observe(v float64, bucket int, doSparse bool) {
if frac == 0.5 {
key--
}
div := 1 << -schema
key = (key + div - 1) / div
offset := (1 << -schema) - 1
key = (key + offset) >> -schema
}
if isInf {
key++
@ -810,7 +817,7 @@ func (h *histogram) observe(v float64, bucket int) {
}
}
// limitSparsebuckets applies a strategy to limit the number of populated sparse
// limitBuckets applies a strategy to limit the number of populated sparse
// buckets. It's generally best effort, and there are situations where the
// number can go higher (if even the lowest resolution isn't enough to reduce
// the number sufficiently, or if the provided counts aren't fully updated yet
@ -1034,15 +1041,23 @@ type HistogramVec struct {
// NewHistogramVec creates a new HistogramVec based on the provided HistogramOpts and
// partitioned by the given label names.
func NewHistogramVec(opts HistogramOpts, labelNames []string) *HistogramVec {
desc := NewDesc(
return V2.NewHistogramVec(HistogramVecOpts{
HistogramOpts: opts,
VariableLabels: UnconstrainedLabels(labelNames),
})
}
// NewHistogramVec creates a new HistogramVec based on the provided HistogramVecOpts.
func (v2) NewHistogramVec(opts HistogramVecOpts) *HistogramVec {
desc := V2.NewDesc(
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
opts.Help,
labelNames,
opts.VariableLabels,
opts.ConstLabels,
)
return &HistogramVec{
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
return newHistogram(desc, opts, lvs...)
return newHistogram(desc, opts.HistogramOpts, lvs...)
}),
}
}

View File

@ -32,6 +32,78 @@ import (
// create a Desc.
type Labels map[string]string
// ConstrainedLabels represents a label name and its constrain function
// to normalize label values. This type is commonly used when constructing
// metric vector Collectors.
type ConstrainedLabel struct {
Name string
Constraint func(string) string
}
func (cl ConstrainedLabel) Constrain(v string) string {
if cl.Constraint == nil {
return v
}
return cl.Constraint(v)
}
// ConstrainableLabels is an interface that allows creating of labels that can
// be optionally constrained.
//
// prometheus.V2().NewCounterVec(CounterVecOpts{
// CounterOpts: {...}, // Usual CounterOpts fields
// VariableLabels: []ConstrainedLabels{
// {Name: "A"},
// {Name: "B", Constraint: func(v string) string { ... }},
// },
// })
type ConstrainableLabels interface {
constrainedLabels() ConstrainedLabels
labelNames() []string
}
// ConstrainedLabels represents a collection of label name -> constrain function
// to normalize label values. This type is commonly used when constructing
// metric vector Collectors.
type ConstrainedLabels []ConstrainedLabel
func (cls ConstrainedLabels) constrainedLabels() ConstrainedLabels {
return cls
}
func (cls ConstrainedLabels) labelNames() []string {
names := make([]string, len(cls))
for i, label := range cls {
names[i] = label.Name
}
return names
}
// UnconstrainedLabels represents collection of label without any constraint on
// their value. Thus, it is simply a collection of label names.
//
// UnconstrainedLabels([]string{ "A", "B" })
//
// is equivalent to
//
// ConstrainedLabels {
// { Name: "A" },
// { Name: "B" },
// }
type UnconstrainedLabels []string
func (uls UnconstrainedLabels) constrainedLabels() ConstrainedLabels {
constrainedLabels := make([]ConstrainedLabel, len(uls))
for i, l := range uls {
constrainedLabels[i] = ConstrainedLabel{Name: l}
}
return constrainedLabels
}
func (uls UnconstrainedLabels) labelNames() []string {
return uls
}
// reservedLabelPrefix is a prefix which is not legal in user-supplied
// label names.
const reservedLabelPrefix = "__"

View File

@ -20,11 +20,9 @@ import (
"strings"
"time"
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
"github.com/prometheus/common/model"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/model"
"google.golang.org/protobuf/proto"
)
var separatorByteSlice = []byte{model.SeparatorByte} // For convenient use with xxhash.

View File

@ -37,6 +37,7 @@ import (
"fmt"
"io"
"net/http"
"strconv"
"strings"
"sync"
"time"
@ -47,9 +48,10 @@ import (
)
const (
contentTypeHeader = "Content-Type"
contentEncodingHeader = "Content-Encoding"
acceptEncodingHeader = "Accept-Encoding"
contentTypeHeader = "Content-Type"
contentEncodingHeader = "Content-Encoding"
acceptEncodingHeader = "Accept-Encoding"
processStartTimeHeader = "Process-Start-Time-Unix"
)
var gzipPool = sync.Pool{
@ -121,6 +123,9 @@ func HandlerForTransactional(reg prometheus.TransactionalGatherer, opts HandlerO
}
h := http.HandlerFunc(func(rsp http.ResponseWriter, req *http.Request) {
if !opts.ProcessStartTime.IsZero() {
rsp.Header().Set(processStartTimeHeader, strconv.FormatInt(opts.ProcessStartTime.Unix(), 10))
}
if inFlightSem != nil {
select {
case inFlightSem <- struct{}{}: // All good, carry on.
@ -366,6 +371,14 @@ type HandlerOpts struct {
// (which changes the identity of the resulting series on the Prometheus
// server).
EnableOpenMetrics bool
// ProcessStartTime allows setting process start timevalue that will be exposed
// with "Process-Start-Time-Unix" response header along with the metrics
// payload. This allow callers to have efficient transformations to cumulative
// counters (e.g. OpenTelemetry) or generally _created timestamp estimation per
// scrape target.
// NOTE: This feature is experimental and not covered by OpenMetrics or Prometheus
// exposition format.
ProcessStartTime time.Time
}
// gzipAccepted returns whether the client will accept gzip-encoded content.

View File

@ -68,16 +68,17 @@ func InstrumentRoundTripperCounter(counter *prometheus.CounterVec, next http.Rou
o.apply(rtOpts)
}
code, method := checkLabels(counter)
// Curry the counter with dynamic labels before checking the remaining labels.
code, method := checkLabels(counter.MustCurryWith(rtOpts.emptyDynamicLabels()))
return func(r *http.Request) (*http.Response, error) {
resp, err := next.RoundTrip(r)
if err == nil {
addWithExemplar(
counter.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)),
1,
rtOpts.getExemplarFn(r.Context()),
)
l := labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)
for label, resolve := range rtOpts.extraLabelsFromCtx {
l[label] = resolve(resp.Request.Context())
}
addWithExemplar(counter.With(l), 1, rtOpts.getExemplarFn(r.Context()))
}
return resp, err
}
@ -110,17 +111,18 @@ func InstrumentRoundTripperDuration(obs prometheus.ObserverVec, next http.RoundT
o.apply(rtOpts)
}
code, method := checkLabels(obs)
// Curry the observer with dynamic labels before checking the remaining labels.
code, method := checkLabels(obs.MustCurryWith(rtOpts.emptyDynamicLabels()))
return func(r *http.Request) (*http.Response, error) {
start := time.Now()
resp, err := next.RoundTrip(r)
if err == nil {
observeWithExemplar(
obs.With(labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)),
time.Since(start).Seconds(),
rtOpts.getExemplarFn(r.Context()),
)
l := labels(code, method, r.Method, resp.StatusCode, rtOpts.extraMethods...)
for label, resolve := range rtOpts.extraLabelsFromCtx {
l[label] = resolve(resp.Request.Context())
}
observeWithExemplar(obs.With(l), time.Since(start).Seconds(), rtOpts.getExemplarFn(r.Context()))
}
return resp, err
}

View File

@ -87,7 +87,8 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, op
o.apply(hOpts)
}
code, method := checkLabels(obs)
// Curry the observer with dynamic labels before checking the remaining labels.
code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels()))
if code {
return func(w http.ResponseWriter, r *http.Request) {
@ -95,23 +96,22 @@ func InstrumentHandlerDuration(obs prometheus.ObserverVec, next http.Handler, op
d := newDelegator(w, nil)
next.ServeHTTP(d, r)
observeWithExemplar(
obs.With(labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)),
time.Since(now).Seconds(),
hOpts.getExemplarFn(r.Context()),
)
l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)
for label, resolve := range hOpts.extraLabelsFromCtx {
l[label] = resolve(r.Context())
}
observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context()))
}
}
return func(w http.ResponseWriter, r *http.Request) {
now := time.Now()
next.ServeHTTP(w, r)
observeWithExemplar(
obs.With(labels(code, method, r.Method, 0, hOpts.extraMethods...)),
time.Since(now).Seconds(),
hOpts.getExemplarFn(r.Context()),
)
l := labels(code, method, r.Method, 0, hOpts.extraMethods...)
for label, resolve := range hOpts.extraLabelsFromCtx {
l[label] = resolve(r.Context())
}
observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context()))
}
}
@ -138,28 +138,30 @@ func InstrumentHandlerCounter(counter *prometheus.CounterVec, next http.Handler,
o.apply(hOpts)
}
code, method := checkLabels(counter)
// Curry the counter with dynamic labels before checking the remaining labels.
code, method := checkLabels(counter.MustCurryWith(hOpts.emptyDynamicLabels()))
if code {
return func(w http.ResponseWriter, r *http.Request) {
d := newDelegator(w, nil)
next.ServeHTTP(d, r)
addWithExemplar(
counter.With(labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)),
1,
hOpts.getExemplarFn(r.Context()),
)
l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)
for label, resolve := range hOpts.extraLabelsFromCtx {
l[label] = resolve(r.Context())
}
addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r.Context()))
}
}
return func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, r)
addWithExemplar(
counter.With(labels(code, method, r.Method, 0, hOpts.extraMethods...)),
1,
hOpts.getExemplarFn(r.Context()),
)
l := labels(code, method, r.Method, 0, hOpts.extraMethods...)
for label, resolve := range hOpts.extraLabelsFromCtx {
l[label] = resolve(r.Context())
}
addWithExemplar(counter.With(l), 1, hOpts.getExemplarFn(r.Context()))
}
}
@ -191,16 +193,17 @@ func InstrumentHandlerTimeToWriteHeader(obs prometheus.ObserverVec, next http.Ha
o.apply(hOpts)
}
code, method := checkLabels(obs)
// Curry the observer with dynamic labels before checking the remaining labels.
code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels()))
return func(w http.ResponseWriter, r *http.Request) {
now := time.Now()
d := newDelegator(w, func(status int) {
observeWithExemplar(
obs.With(labels(code, method, r.Method, status, hOpts.extraMethods...)),
time.Since(now).Seconds(),
hOpts.getExemplarFn(r.Context()),
)
l := labels(code, method, r.Method, status, hOpts.extraMethods...)
for label, resolve := range hOpts.extraLabelsFromCtx {
l[label] = resolve(r.Context())
}
observeWithExemplar(obs.With(l), time.Since(now).Seconds(), hOpts.getExemplarFn(r.Context()))
})
next.ServeHTTP(d, r)
}
@ -231,28 +234,32 @@ func InstrumentHandlerRequestSize(obs prometheus.ObserverVec, next http.Handler,
o.apply(hOpts)
}
code, method := checkLabels(obs)
// Curry the observer with dynamic labels before checking the remaining labels.
code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels()))
if code {
return func(w http.ResponseWriter, r *http.Request) {
d := newDelegator(w, nil)
next.ServeHTTP(d, r)
size := computeApproximateRequestSize(r)
observeWithExemplar(
obs.With(labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)),
float64(size),
hOpts.getExemplarFn(r.Context()),
)
l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)
for label, resolve := range hOpts.extraLabelsFromCtx {
l[label] = resolve(r.Context())
}
observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r.Context()))
}
}
return func(w http.ResponseWriter, r *http.Request) {
next.ServeHTTP(w, r)
size := computeApproximateRequestSize(r)
observeWithExemplar(
obs.With(labels(code, method, r.Method, 0, hOpts.extraMethods...)),
float64(size),
hOpts.getExemplarFn(r.Context()),
)
l := labels(code, method, r.Method, 0, hOpts.extraMethods...)
for label, resolve := range hOpts.extraLabelsFromCtx {
l[label] = resolve(r.Context())
}
observeWithExemplar(obs.With(l), float64(size), hOpts.getExemplarFn(r.Context()))
}
}
@ -281,16 +288,18 @@ func InstrumentHandlerResponseSize(obs prometheus.ObserverVec, next http.Handler
o.apply(hOpts)
}
code, method := checkLabels(obs)
// Curry the observer with dynamic labels before checking the remaining labels.
code, method := checkLabels(obs.MustCurryWith(hOpts.emptyDynamicLabels()))
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
d := newDelegator(w, nil)
next.ServeHTTP(d, r)
observeWithExemplar(
obs.With(labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)),
float64(d.Written()),
hOpts.getExemplarFn(r.Context()),
)
l := labels(code, method, r.Method, d.Status(), hOpts.extraMethods...)
for label, resolve := range hOpts.extraLabelsFromCtx {
l[label] = resolve(r.Context())
}
observeWithExemplar(obs.With(l), float64(d.Written()), hOpts.getExemplarFn(r.Context()))
})
}

View File

@ -24,14 +24,32 @@ type Option interface {
apply(*options)
}
// LabelValueFromCtx are used to compute the label value from request context.
// Context can be filled with values from request through middleware.
type LabelValueFromCtx func(ctx context.Context) string
// options store options for both a handler or round tripper.
type options struct {
extraMethods []string
getExemplarFn func(requestCtx context.Context) prometheus.Labels
extraMethods []string
getExemplarFn func(requestCtx context.Context) prometheus.Labels
extraLabelsFromCtx map[string]LabelValueFromCtx
}
func defaultOptions() *options {
return &options{getExemplarFn: func(ctx context.Context) prometheus.Labels { return nil }}
return &options{
getExemplarFn: func(ctx context.Context) prometheus.Labels { return nil },
extraLabelsFromCtx: map[string]LabelValueFromCtx{},
}
}
func (o *options) emptyDynamicLabels() prometheus.Labels {
labels := prometheus.Labels{}
for label := range o.extraLabelsFromCtx {
labels[label] = ""
}
return labels
}
type optionApplyFunc func(*options)
@ -48,11 +66,19 @@ func WithExtraMethods(methods ...string) Option {
})
}
// WithExemplarFromContext adds allows to put a hook to all counter and histogram metrics.
// If the hook function returns non-nil labels, exemplars will be added for that request, otherwise metric
// will get instrumented without exemplar.
// WithExemplarFromContext allows to inject function that will get exemplar from context that will be put to counter and histogram metrics.
// If the function returns nil labels or the metric does not support exemplars, no exemplar will be added (noop), but
// metric will continue to observe/increment.
func WithExemplarFromContext(getExemplarFn func(requestCtx context.Context) prometheus.Labels) Option {
return optionApplyFunc(func(o *options) {
o.getExemplarFn = getExemplarFn
})
}
// WithLabelFromCtx registers a label for dynamic resolution with access to context.
// See the example for ExampleInstrumentHandlerWithLabelResolver for example usage
func WithLabelFromCtx(name string, valueFn LabelValueFromCtx) Option {
return optionApplyFunc(func(o *options) {
o.extraLabelsFromCtx[name] = valueFn
})
}

View File

@ -21,18 +21,17 @@ import (
"path/filepath"
"runtime"
"sort"
"strconv"
"strings"
"sync"
"unicode/utf8"
"github.com/cespare/xxhash/v2"
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
"github.com/prometheus/common/expfmt"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/client_golang/prometheus/internal"
"github.com/cespare/xxhash/v2"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/expfmt"
"google.golang.org/protobuf/proto"
)
const (
@ -933,6 +932,10 @@ func checkMetricConsistency(
h.WriteString(lp.GetValue())
h.Write(separatorByteSlice)
}
if dtoMetric.TimestampMs != nil {
h.WriteString(strconv.FormatInt(*(dtoMetric.TimestampMs), 10))
h.Write(separatorByteSlice)
}
hSum := h.Sum64()
if _, exists := metricHashes[hSum]; exists {
return fmt.Errorf(
@ -962,7 +965,7 @@ func checkDescConsistency(
copy(lpsFromDesc, desc.constLabelPairs)
for _, l := range desc.variableLabels {
lpsFromDesc = append(lpsFromDesc, &dto.LabelPair{
Name: proto.String(l),
Name: proto.String(l.Name),
})
}
if len(lpsFromDesc) != len(dtoMetric.Label) {

View File

@ -22,11 +22,10 @@ import (
"sync/atomic"
"time"
"github.com/beorn7/perks/quantile"
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
dto "github.com/prometheus/client_model/go"
"github.com/beorn7/perks/quantile"
"google.golang.org/protobuf/proto"
)
// quantileLabel is used for the label that defines the quantile in a
@ -148,6 +147,18 @@ type SummaryOpts struct {
BufCap uint32
}
// SummaryVecOpts bundles the options to create a SummaryVec metric.
// It is mandatory to set SummaryOpts, see there for mandatory fields. VariableLabels
// is optional and can safely be left to its default value.
type SummaryVecOpts struct {
SummaryOpts
// VariableLabels are used to partition the metric vector by the given set
// of labels. Each label value will be constrained with the optional Contraint
// function, if provided.
VariableLabels ConstrainableLabels
}
// Problem with the sliding-window decay algorithm... The Merge method of
// perk/quantile is actually not working as advertised - and it might be
// unfixable, as the underlying algorithm is apparently not capable of merging
@ -178,11 +189,11 @@ func NewSummary(opts SummaryOpts) Summary {
func newSummary(desc *Desc, opts SummaryOpts, labelValues ...string) Summary {
if len(desc.variableLabels) != len(labelValues) {
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels, labelValues))
panic(makeInconsistentCardinalityError(desc.fqName, desc.variableLabels.labelNames(), labelValues))
}
for _, n := range desc.variableLabels {
if n == quantileLabel {
if n.Name == quantileLabel {
panic(errQuantileLabelNotAllowed)
}
}
@ -530,20 +541,28 @@ type SummaryVec struct {
// it is handled by the Prometheus server internally, “quantile” is an illegal
// label name. NewSummaryVec will panic if this label name is used.
func NewSummaryVec(opts SummaryOpts, labelNames []string) *SummaryVec {
for _, ln := range labelNames {
return V2.NewSummaryVec(SummaryVecOpts{
SummaryOpts: opts,
VariableLabels: UnconstrainedLabels(labelNames),
})
}
// NewSummaryVec creates a new SummaryVec based on the provided SummaryVecOpts.
func (v2) NewSummaryVec(opts SummaryVecOpts) *SummaryVec {
for _, ln := range opts.VariableLabels.labelNames() {
if ln == quantileLabel {
panic(errQuantileLabelNotAllowed)
}
}
desc := NewDesc(
desc := V2.NewDesc(
BuildFQName(opts.Namespace, opts.Subsystem, opts.Name),
opts.Help,
labelNames,
opts.VariableLabels,
opts.ConstLabels,
)
return &SummaryVec{
MetricVec: NewMetricVec(desc, func(lvs ...string) Metric {
return newSummary(desc, opts, lvs...)
return newSummary(desc, opts.SummaryOpts, lvs...)
}),
}
}

View File

@ -23,7 +23,9 @@ type Timer struct {
}
// NewTimer creates a new Timer. The provided Observer is used to observe a
// duration in seconds. Timer is usually used to time a function call in the
// duration in seconds. If the Observer implements ExemplarObserver, passing exemplar
// later on will be also supported.
// Timer is usually used to time a function call in the
// following way:
//
// func TimeMe() {
@ -31,6 +33,14 @@ type Timer struct {
// defer timer.ObserveDuration()
// // Do actual work.
// }
//
// or
//
// func TimeMeWithExemplar() {
// timer := NewTimer(myHistogram)
// defer timer.ObserveDurationWithExemplar(exemplar)
// // Do actual work.
// }
func NewTimer(o Observer) *Timer {
return &Timer{
begin: time.Now(),
@ -53,3 +63,19 @@ func (t *Timer) ObserveDuration() time.Duration {
}
return d
}
// ObserveDurationWithExemplar is like ObserveDuration, but it will also
// observe exemplar with the duration unless exemplar is nil or provided Observer can't
// be casted to ExemplarObserver.
func (t *Timer) ObserveDurationWithExemplar(exemplar Labels) time.Duration {
d := time.Since(t.begin)
eo, ok := t.observer.(ExemplarObserver)
if ok && exemplar != nil {
eo.ObserveWithExemplar(d.Seconds(), exemplar)
return d
}
if t.observer != nil {
t.observer.Observe(d.Seconds())
}
return d
}

View File

@ -19,13 +19,11 @@ import (
"time"
"unicode/utf8"
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
"google.golang.org/protobuf/types/known/timestamppb"
"github.com/prometheus/client_golang/prometheus/internal"
dto "github.com/prometheus/client_model/go"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/timestamppb"
)
// ValueType is an enumeration of metric types that represent a simple value.
@ -188,9 +186,9 @@ func MakeLabelPairs(desc *Desc, labelValues []string) []*dto.LabelPair {
return desc.constLabelPairs
}
labelPairs := make([]*dto.LabelPair, 0, totalLen)
for i, n := range desc.variableLabels {
for i, l := range desc.variableLabels {
labelPairs = append(labelPairs, &dto.LabelPair{
Name: proto.String(n),
Name: proto.String(l.Name),
Value: proto.String(labelValues[i]),
})
}

View File

@ -20,6 +20,24 @@ import (
"github.com/prometheus/common/model"
)
var labelsPool = &sync.Pool{
New: func() interface{} {
return make(Labels)
},
}
func getLabelsFromPool() Labels {
return labelsPool.Get().(Labels)
}
func putLabelsToPool(labels Labels) {
for k := range labels {
delete(labels, k)
}
labelsPool.Put(labels)
}
// MetricVec is a Collector to bundle metrics of the same name that differ in
// their label values. MetricVec is not used directly but as a building block
// for implementations of vectors of a given metric type, like GaugeVec,
@ -72,6 +90,7 @@ func NewMetricVec(desc *Desc, newMetric func(lvs ...string) Metric) *MetricVec {
// with a performance overhead (for creating and processing the Labels map).
// See also the CounterVec example.
func (m *MetricVec) DeleteLabelValues(lvs ...string) bool {
lvs = constrainLabelValues(m.desc, lvs, m.curry)
h, err := m.hashLabelValues(lvs)
if err != nil {
return false
@ -91,6 +110,9 @@ func (m *MetricVec) DeleteLabelValues(lvs ...string) bool {
// This method is used for the same purpose as DeleteLabelValues(...string). See
// there for pros and cons of the two methods.
func (m *MetricVec) Delete(labels Labels) bool {
labels = constrainLabels(m.desc, labels)
defer putLabelsToPool(labels)
h, err := m.hashLabels(labels)
if err != nil {
return false
@ -106,6 +128,9 @@ func (m *MetricVec) Delete(labels Labels) bool {
// Note that curried labels will never be matched if deleting from the curried vector.
// To match curried labels with DeletePartialMatch, it must be called on the base vector.
func (m *MetricVec) DeletePartialMatch(labels Labels) int {
labels = constrainLabels(m.desc, labels)
defer putLabelsToPool(labels)
return m.metricMap.deleteByLabels(labels, m.curry)
}
@ -145,10 +170,10 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) {
iCurry int
)
for i, label := range m.desc.variableLabels {
val, ok := labels[label]
val, ok := labels[label.Name]
if iCurry < len(oldCurry) && oldCurry[iCurry].index == i {
if ok {
return nil, fmt.Errorf("label name %q is already curried", label)
return nil, fmt.Errorf("label name %q is already curried", label.Name)
}
newCurry = append(newCurry, oldCurry[iCurry])
iCurry++
@ -156,7 +181,7 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) {
if !ok {
continue // Label stays uncurried.
}
newCurry = append(newCurry, curriedLabelValue{i, val})
newCurry = append(newCurry, curriedLabelValue{i, label.Constrain(val)})
}
}
if l := len(oldCurry) + len(labels) - len(newCurry); l > 0 {
@ -199,6 +224,7 @@ func (m *MetricVec) CurryWith(labels Labels) (*MetricVec, error) {
// a wrapper around MetricVec, implementing a vector for a specific Metric
// implementation, for example GaugeVec.
func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
lvs = constrainLabelValues(m.desc, lvs, m.curry)
h, err := m.hashLabelValues(lvs)
if err != nil {
return nil, err
@ -224,6 +250,9 @@ func (m *MetricVec) GetMetricWithLabelValues(lvs ...string) (Metric, error) {
// around MetricVec, implementing a vector for a specific Metric implementation,
// for example GaugeVec.
func (m *MetricVec) GetMetricWith(labels Labels) (Metric, error) {
labels = constrainLabels(m.desc, labels)
defer putLabelsToPool(labels)
h, err := m.hashLabels(labels)
if err != nil {
return nil, err
@ -266,16 +295,16 @@ func (m *MetricVec) hashLabels(labels Labels) (uint64, error) {
iCurry int
)
for i, label := range m.desc.variableLabels {
val, ok := labels[label]
val, ok := labels[label.Name]
if iCurry < len(curry) && curry[iCurry].index == i {
if ok {
return 0, fmt.Errorf("label name %q is already curried", label)
return 0, fmt.Errorf("label name %q is already curried", label.Name)
}
h = m.hashAdd(h, curry[iCurry].value)
iCurry++
} else {
if !ok {
return 0, fmt.Errorf("label name %q missing in label map", label)
return 0, fmt.Errorf("label name %q missing in label map", label.Name)
}
h = m.hashAdd(h, val)
}
@ -453,7 +482,7 @@ func valueMatchesVariableOrCurriedValue(targetValue string, index int, values []
func matchPartialLabels(desc *Desc, values []string, labels Labels, curry []curriedLabelValue) bool {
for l, v := range labels {
// Check if the target label exists in our metrics and get the index.
varLabelIndex, validLabel := indexOf(l, desc.variableLabels)
varLabelIndex, validLabel := indexOf(l, desc.variableLabels.labelNames())
if validLabel {
// Check the value of that label against the target value.
// We don't consider curried values in partial matches.
@ -605,7 +634,7 @@ func matchLabels(desc *Desc, values []string, labels Labels, curry []curriedLabe
iCurry++
continue
}
if values[i] != labels[k] {
if values[i] != labels[k.Name] {
return false
}
}
@ -621,7 +650,7 @@ func extractLabelValues(desc *Desc, labels Labels, curry []curriedLabelValue) []
iCurry++
continue
}
labelValues[i] = labels[k]
labelValues[i] = labels[k.Name]
}
return labelValues
}
@ -640,3 +669,35 @@ func inlineLabelValues(lvs []string, curry []curriedLabelValue) []string {
}
return labelValues
}
func constrainLabels(desc *Desc, labels Labels) Labels {
constrainedLabels := getLabelsFromPool()
for l, v := range labels {
if i, ok := indexOf(l, desc.variableLabels.labelNames()); ok {
v = desc.variableLabels[i].Constrain(v)
}
constrainedLabels[l] = v
}
return constrainedLabels
}
func constrainLabelValues(desc *Desc, lvs []string, curry []curriedLabelValue) []string {
constrainedValues := make([]string, len(lvs))
var iCurry, iLVs int
for i := 0; i < len(lvs)+len(curry); i++ {
if iCurry < len(curry) && curry[iCurry].index == i {
iCurry++
continue
}
if i < len(desc.variableLabels) {
constrainedValues[iLVs] = desc.variableLabels[i].Constrain(lvs[iLVs])
} else {
constrainedValues[iLVs] = lvs[iLVs]
}
iLVs++
}
return constrainedValues
}

View File

@ -0,0 +1,23 @@
// Copyright 2022 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package prometheus
type v2 struct{}
// V2 is a struct that can be referenced to access experimental API that might
// be present in v2 of client golang someday. It offers extended functionality
// of v1 with slightly changed API. It is acceptable to use some pieces from v1
// and e.g `prometheus.NewGauge` and some from v2 e.g. `prometheus.V2.NewDesc`
// in the same codebase.
var V2 = v2{}

View File

@ -17,12 +17,10 @@ import (
"fmt"
"sort"
//nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/golang/protobuf/proto"
"github.com/prometheus/client_golang/prometheus/internal"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/client_golang/prometheus/internal"
"google.golang.org/protobuf/proto"
)
// WrapRegistererWith returns a Registerer wrapping the provided
@ -206,7 +204,7 @@ func wrapDesc(desc *Desc, prefix string, labels Labels) *Desc {
constLabels[ln] = lv
}
// NewDesc will do remaining validations.
newDesc := NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels)
newDesc := V2.NewDesc(prefix+desc.fqName, desc.help, desc.variableLabels, constLabels)
// Propagate errors if there was any. This will override any errer
// created by NewDesc above, i.e. earlier errors get precedence.
if desc.err != nil {

File diff suppressed because it is too large Load Diff

View File

@ -115,32 +115,31 @@ func (d *protoDecoder) Decode(v *dto.MetricFamily) error {
// textDecoder implements the Decoder interface for the text protocol.
type textDecoder struct {
r io.Reader
p TextParser
fams []*dto.MetricFamily
fams map[string]*dto.MetricFamily
err error
}
// Decode implements the Decoder interface.
func (d *textDecoder) Decode(v *dto.MetricFamily) error {
// TODO(fabxc): Wrap this as a line reader to make streaming safer.
if len(d.fams) == 0 {
// No cached metric families, read everything and parse metrics.
fams, err := d.p.TextToMetricFamilies(d.r)
if err != nil {
return err
}
if len(fams) == 0 {
return io.EOF
}
d.fams = make([]*dto.MetricFamily, 0, len(fams))
for _, f := range fams {
d.fams = append(d.fams, f)
if d.err == nil {
// Read all metrics in one shot.
var p TextParser
d.fams, d.err = p.TextToMetricFamilies(d.r)
// If we don't get an error, store io.EOF for the end.
if d.err == nil {
d.err = io.EOF
}
}
*v = *d.fams[0]
d.fams = d.fams[1:]
return nil
// Pick off one MetricFamily per Decode until there's nothing left.
for key, fam := range d.fams {
v.Name = fam.Name
v.Help = fam.Help
v.Type = fam.Type
v.Metric = fam.Metric
delete(d.fams, key)
return nil
}
return d.err
}
// SampleDecoder wraps a Decoder to extract samples from the metric families

View File

@ -18,9 +18,9 @@ import (
"io"
"net/http"
"github.com/golang/protobuf/proto" //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/matttproud/golang_protobuf_extensions/pbutil"
"github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg"
"google.golang.org/protobuf/encoding/prototext"
dto "github.com/prometheus/client_model/go"
)
@ -99,8 +99,11 @@ func NegotiateIncludingOpenMetrics(h http.Header) Format {
if ac.Type == "text" && ac.SubType == "plain" && (ver == TextVersion || ver == "") {
return FmtText
}
if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion || ver == "") {
return FmtOpenMetrics
if ac.Type+"/"+ac.SubType == OpenMetricsType && (ver == OpenMetricsVersion_0_0_1 || ver == OpenMetricsVersion_1_0_0 || ver == "") {
if ver == OpenMetricsVersion_1_0_0 {
return FmtOpenMetrics_1_0_0
}
return FmtOpenMetrics_0_0_1
}
}
return FmtText
@ -133,7 +136,7 @@ func NewEncoder(w io.Writer, format Format) Encoder {
case FmtProtoText:
return encoderCloser{
encode: func(v *dto.MetricFamily) error {
_, err := fmt.Fprintln(w, proto.MarshalTextString(v))
_, err := fmt.Fprintln(w, prototext.Format(v))
return err
},
close: func() error { return nil },
@ -146,7 +149,7 @@ func NewEncoder(w io.Writer, format Format) Encoder {
},
close: func() error { return nil },
}
case FmtOpenMetrics:
case FmtOpenMetrics_0_0_1, FmtOpenMetrics_1_0_0:
return encoderCloser{
encode: func(v *dto.MetricFamily) error {
_, err := MetricFamilyToOpenMetrics(w, v)

View File

@ -19,20 +19,22 @@ type Format string
// Constants to assemble the Content-Type values for the different wire protocols.
const (
TextVersion = "0.0.4"
ProtoType = `application/vnd.google.protobuf`
ProtoProtocol = `io.prometheus.client.MetricFamily`
ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";"
OpenMetricsType = `application/openmetrics-text`
OpenMetricsVersion = "0.0.1"
TextVersion = "0.0.4"
ProtoType = `application/vnd.google.protobuf`
ProtoProtocol = `io.prometheus.client.MetricFamily`
ProtoFmt = ProtoType + "; proto=" + ProtoProtocol + ";"
OpenMetricsType = `application/openmetrics-text`
OpenMetricsVersion_0_0_1 = "0.0.1"
OpenMetricsVersion_1_0_0 = "1.0.0"
// The Content-Type values for the different wire protocols.
FmtUnknown Format = `<unknown>`
FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8`
FmtProtoDelim Format = ProtoFmt + ` encoding=delimited`
FmtProtoText Format = ProtoFmt + ` encoding=text`
FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text`
FmtOpenMetrics Format = OpenMetricsType + `; version=` + OpenMetricsVersion + `; charset=utf-8`
FmtUnknown Format = `<unknown>`
FmtText Format = `text/plain; version=` + TextVersion + `; charset=utf-8`
FmtProtoDelim Format = ProtoFmt + ` encoding=delimited`
FmtProtoText Format = ProtoFmt + ` encoding=text`
FmtProtoCompact Format = ProtoFmt + ` encoding=compact-text`
FmtOpenMetrics_1_0_0 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_1_0_0 + `; charset=utf-8`
FmtOpenMetrics_0_0_1 Format = OpenMetricsType + `; version=` + OpenMetricsVersion_0_0_1 + `; charset=utf-8`
)
const (

View File

@ -21,8 +21,8 @@ import "bytes"
// Fuzz text metric parser with with github.com/dvyukov/go-fuzz:
//
// go-fuzz-build github.com/prometheus/common/expfmt
// go-fuzz -bin expfmt-fuzz.zip -workdir fuzz
// go-fuzz-build github.com/prometheus/common/expfmt
// go-fuzz -bin expfmt-fuzz.zip -workdir fuzz
//
// Further input samples should go in the folder fuzz/corpus.
func Fuzz(in []byte) int {

View File

@ -46,20 +46,20 @@ import (
// missing features and peculiarities to avoid complications when switching from
// Prometheus to OpenMetrics or vice versa:
//
// - Counters are expected to have the `_total` suffix in their metric name. In
// the output, the suffix will be truncated from the `# TYPE` and `# HELP`
// line. A counter with a missing `_total` suffix is not an error. However,
// its type will be set to `unknown` in that case to avoid invalid OpenMetrics
// output.
// - Counters are expected to have the `_total` suffix in their metric name. In
// the output, the suffix will be truncated from the `# TYPE` and `# HELP`
// line. A counter with a missing `_total` suffix is not an error. However,
// its type will be set to `unknown` in that case to avoid invalid OpenMetrics
// output.
//
// - No support for the following (optional) features: `# UNIT` line, `_created`
// line, info type, stateset type, gaugehistogram type.
// - No support for the following (optional) features: `# UNIT` line, `_created`
// line, info type, stateset type, gaugehistogram type.
//
// - The size of exemplar labels is not checked (i.e. it's possible to create
// exemplars that are larger than allowed by the OpenMetrics specification).
// - The size of exemplar labels is not checked (i.e. it's possible to create
// exemplars that are larger than allowed by the OpenMetrics specification).
//
// - The value of Counters is not checked. (OpenMetrics doesn't allow counters
// with a `NaN` value.)
// - The value of Counters is not checked. (OpenMetrics doesn't allow counters
// with a `NaN` value.)
func MetricFamilyToOpenMetrics(out io.Writer, in *dto.MetricFamily) (written int, err error) {
name := in.GetName()
if name == "" {

View File

@ -17,7 +17,6 @@ import (
"bufio"
"fmt"
"io"
"io/ioutil"
"math"
"strconv"
"strings"
@ -44,7 +43,7 @@ const (
var (
bufPool = sync.Pool{
New: func() interface{} {
return bufio.NewWriter(ioutil.Discard)
return bufio.NewWriter(io.Discard)
},
}
numBufPool = sync.Pool{

View File

@ -24,8 +24,8 @@ import (
dto "github.com/prometheus/client_model/go"
"github.com/golang/protobuf/proto" //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility.
"github.com/prometheus/common/model"
"google.golang.org/protobuf/proto"
)
// A stateFn is a function that represents a state in a state machine. By
@ -142,9 +142,13 @@ func (p *TextParser) reset(in io.Reader) {
func (p *TextParser) startOfLine() stateFn {
p.lineCount++
if p.skipBlankTab(); p.err != nil {
// End of input reached. This is the only case where
// that is not an error but a signal that we are done.
p.err = nil
// This is the only place that we expect to see io.EOF,
// which is not an error but the signal that we are done.
// Any other error that happens to align with the start of
// a line is still an error.
if p.err == io.EOF {
p.err = nil
}
return nil
}
switch p.currentByte {

View File

@ -11,18 +11,18 @@ Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
Neither the name of the Open Knowledge Foundation Ltd. nor the
names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
Neither the name of the Open Knowledge Foundation Ltd. nor the
names of its contributors may be used to endorse or promote
products derived from this software without specific prior written
permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
@ -35,8 +35,6 @@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package goautoneg

View File

@ -18,7 +18,6 @@ import (
"errors"
"fmt"
"math"
"regexp"
"strconv"
"strings"
"time"
@ -183,54 +182,78 @@ func (d *Duration) Type() string {
return "duration"
}
var durationRE = regexp.MustCompile("^(([0-9]+)y)?(([0-9]+)w)?(([0-9]+)d)?(([0-9]+)h)?(([0-9]+)m)?(([0-9]+)s)?(([0-9]+)ms)?$")
func isdigit(c byte) bool { return c >= '0' && c <= '9' }
// Units are required to go in order from biggest to smallest.
// This guards against confusion from "1m1d" being 1 minute + 1 day, not 1 month + 1 day.
var unitMap = map[string]struct {
pos int
mult uint64
}{
"ms": {7, uint64(time.Millisecond)},
"s": {6, uint64(time.Second)},
"m": {5, uint64(time.Minute)},
"h": {4, uint64(time.Hour)},
"d": {3, uint64(24 * time.Hour)},
"w": {2, uint64(7 * 24 * time.Hour)},
"y": {1, uint64(365 * 24 * time.Hour)},
}
// ParseDuration parses a string into a time.Duration, assuming that a year
// always has 365d, a week always has 7d, and a day always has 24h.
func ParseDuration(durationStr string) (Duration, error) {
switch durationStr {
func ParseDuration(s string) (Duration, error) {
switch s {
case "0":
// Allow 0 without a unit.
return 0, nil
case "":
return 0, errors.New("empty duration string")
}
matches := durationRE.FindStringSubmatch(durationStr)
if matches == nil {
return 0, fmt.Errorf("not a valid duration string: %q", durationStr)
}
var dur time.Duration
// Parse the match at pos `pos` in the regex and use `mult` to turn that
// into ms, then add that value to the total parsed duration.
var overflowErr error
m := func(pos int, mult time.Duration) {
if matches[pos] == "" {
return
orig := s
var dur uint64
lastUnitPos := 0
for s != "" {
if !isdigit(s[0]) {
return 0, fmt.Errorf("not a valid duration string: %q", orig)
}
n, _ := strconv.Atoi(matches[pos])
// Consume [0-9]*
i := 0
for ; i < len(s) && isdigit(s[i]); i++ {
}
v, err := strconv.ParseUint(s[:i], 10, 0)
if err != nil {
return 0, fmt.Errorf("not a valid duration string: %q", orig)
}
s = s[i:]
// Consume unit.
for i = 0; i < len(s) && !isdigit(s[i]); i++ {
}
if i == 0 {
return 0, fmt.Errorf("not a valid duration string: %q", orig)
}
u := s[:i]
s = s[i:]
unit, ok := unitMap[u]
if !ok {
return 0, fmt.Errorf("unknown unit %q in duration %q", u, orig)
}
if unit.pos <= lastUnitPos { // Units must go in order from biggest to smallest.
return 0, fmt.Errorf("not a valid duration string: %q", orig)
}
lastUnitPos = unit.pos
// Check if the provided duration overflows time.Duration (> ~ 290years).
if n > int((1<<63-1)/mult/time.Millisecond) {
overflowErr = errors.New("duration out of range")
if v > 1<<63/unit.mult {
return 0, errors.New("duration out of range")
}
d := time.Duration(n) * time.Millisecond
dur += d * mult
if dur < 0 {
overflowErr = errors.New("duration out of range")
dur += v * unit.mult
if dur > 1<<63-1 {
return 0, errors.New("duration out of range")
}
}
m(2, 1000*60*60*24*365) // y
m(4, 1000*60*60*24*7) // w
m(6, 1000*60*60*24) // d
m(8, 1000*60*60) // h
m(10, 1000*60) // m
m(12, 1000) // s
m(14, 1) // ms
return Duration(dur), overflowErr
return Duration(dur), nil
}
func (d Duration) String() string {

View File

@ -16,20 +16,12 @@ package model
import (
"encoding/json"
"fmt"
"math"
"sort"
"strconv"
"strings"
)
var (
// ZeroSamplePair is the pseudo zero-value of SamplePair used to signal a
// non-existing sample pair. It is a SamplePair with timestamp Earliest and
// value 0.0. Note that the natural zero value of SamplePair has a timestamp
// of 0, which is possible to appear in a real SamplePair and thus not
// suitable to signal a non-existing SamplePair.
ZeroSamplePair = SamplePair{Timestamp: Earliest}
// ZeroSample is the pseudo zero-value of Sample used to signal a
// non-existing sample. It is a Sample with timestamp Earliest, value 0.0,
// and metric nil. Note that the natural zero value of Sample has a timestamp
@ -38,82 +30,14 @@ var (
ZeroSample = Sample{Timestamp: Earliest}
)
// A SampleValue is a representation of a value for a given sample at a given
// time.
type SampleValue float64
// MarshalJSON implements json.Marshaler.
func (v SampleValue) MarshalJSON() ([]byte, error) {
return json.Marshal(v.String())
}
// UnmarshalJSON implements json.Unmarshaler.
func (v *SampleValue) UnmarshalJSON(b []byte) error {
if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
return fmt.Errorf("sample value must be a quoted string")
}
f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64)
if err != nil {
return err
}
*v = SampleValue(f)
return nil
}
// Equal returns true if the value of v and o is equal or if both are NaN. Note
// that v==o is false if both are NaN. If you want the conventional float
// behavior, use == to compare two SampleValues.
func (v SampleValue) Equal(o SampleValue) bool {
if v == o {
return true
}
return math.IsNaN(float64(v)) && math.IsNaN(float64(o))
}
func (v SampleValue) String() string {
return strconv.FormatFloat(float64(v), 'f', -1, 64)
}
// SamplePair pairs a SampleValue with a Timestamp.
type SamplePair struct {
Timestamp Time
Value SampleValue
}
// MarshalJSON implements json.Marshaler.
func (s SamplePair) MarshalJSON() ([]byte, error) {
t, err := json.Marshal(s.Timestamp)
if err != nil {
return nil, err
}
v, err := json.Marshal(s.Value)
if err != nil {
return nil, err
}
return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil
}
// UnmarshalJSON implements json.Unmarshaler.
func (s *SamplePair) UnmarshalJSON(b []byte) error {
v := [...]json.Unmarshaler{&s.Timestamp, &s.Value}
return json.Unmarshal(b, &v)
}
// Equal returns true if this SamplePair and o have equal Values and equal
// Timestamps. The semantics of Value equality is defined by SampleValue.Equal.
func (s *SamplePair) Equal(o *SamplePair) bool {
return s == o || (s.Value.Equal(o.Value) && s.Timestamp.Equal(o.Timestamp))
}
func (s SamplePair) String() string {
return fmt.Sprintf("%s @[%s]", s.Value, s.Timestamp)
}
// Sample is a sample pair associated with a metric.
// Sample is a sample pair associated with a metric. A single sample must either
// define Value or Histogram but not both. Histogram == nil implies the Value
// field is used, otherwise it should be ignored.
type Sample struct {
Metric Metric `json:"metric"`
Value SampleValue `json:"value"`
Timestamp Time `json:"timestamp"`
Metric Metric `json:"metric"`
Value SampleValue `json:"value"`
Timestamp Time `json:"timestamp"`
Histogram *SampleHistogram `json:"histogram"`
}
// Equal compares first the metrics, then the timestamp, then the value. The
@ -129,11 +53,19 @@ func (s *Sample) Equal(o *Sample) bool {
if !s.Timestamp.Equal(o.Timestamp) {
return false
}
if s.Histogram != nil {
return s.Histogram.Equal(o.Histogram)
}
return s.Value.Equal(o.Value)
}
func (s Sample) String() string {
if s.Histogram != nil {
return fmt.Sprintf("%s => %s", s.Metric, SampleHistogramPair{
Timestamp: s.Timestamp,
Histogram: s.Histogram,
})
}
return fmt.Sprintf("%s => %s", s.Metric, SamplePair{
Timestamp: s.Timestamp,
Value: s.Value,
@ -142,6 +74,19 @@ func (s Sample) String() string {
// MarshalJSON implements json.Marshaler.
func (s Sample) MarshalJSON() ([]byte, error) {
if s.Histogram != nil {
v := struct {
Metric Metric `json:"metric"`
Histogram SampleHistogramPair `json:"histogram"`
}{
Metric: s.Metric,
Histogram: SampleHistogramPair{
Timestamp: s.Timestamp,
Histogram: s.Histogram,
},
}
return json.Marshal(&v)
}
v := struct {
Metric Metric `json:"metric"`
Value SamplePair `json:"value"`
@ -152,21 +97,25 @@ func (s Sample) MarshalJSON() ([]byte, error) {
Value: s.Value,
},
}
return json.Marshal(&v)
}
// UnmarshalJSON implements json.Unmarshaler.
func (s *Sample) UnmarshalJSON(b []byte) error {
v := struct {
Metric Metric `json:"metric"`
Value SamplePair `json:"value"`
Metric Metric `json:"metric"`
Value SamplePair `json:"value"`
Histogram SampleHistogramPair `json:"histogram"`
}{
Metric: s.Metric,
Value: SamplePair{
Timestamp: s.Timestamp,
Value: s.Value,
},
Histogram: SampleHistogramPair{
Timestamp: s.Timestamp,
Histogram: s.Histogram,
},
}
if err := json.Unmarshal(b, &v); err != nil {
@ -174,8 +123,13 @@ func (s *Sample) UnmarshalJSON(b []byte) error {
}
s.Metric = v.Metric
s.Timestamp = v.Value.Timestamp
s.Value = v.Value.Value
if v.Histogram.Histogram != nil {
s.Timestamp = v.Histogram.Timestamp
s.Histogram = v.Histogram.Histogram
} else {
s.Timestamp = v.Value.Timestamp
s.Value = v.Value.Value
}
return nil
}
@ -221,80 +175,76 @@ func (s Samples) Equal(o Samples) bool {
// SampleStream is a stream of Values belonging to an attached COWMetric.
type SampleStream struct {
Metric Metric `json:"metric"`
Values []SamplePair `json:"values"`
Metric Metric `json:"metric"`
Values []SamplePair `json:"values"`
Histograms []SampleHistogramPair `json:"histograms"`
}
func (ss SampleStream) String() string {
vals := make([]string, len(ss.Values))
valuesLength := len(ss.Values)
vals := make([]string, valuesLength+len(ss.Histograms))
for i, v := range ss.Values {
vals[i] = v.String()
}
for i, v := range ss.Histograms {
vals[i+valuesLength] = v.String()
}
return fmt.Sprintf("%s =>\n%s", ss.Metric, strings.Join(vals, "\n"))
}
// Value is a generic interface for values resulting from a query evaluation.
type Value interface {
Type() ValueType
String() string
func (ss SampleStream) MarshalJSON() ([]byte, error) {
if len(ss.Histograms) > 0 && len(ss.Values) > 0 {
v := struct {
Metric Metric `json:"metric"`
Values []SamplePair `json:"values"`
Histograms []SampleHistogramPair `json:"histograms"`
}{
Metric: ss.Metric,
Values: ss.Values,
Histograms: ss.Histograms,
}
return json.Marshal(&v)
} else if len(ss.Histograms) > 0 {
v := struct {
Metric Metric `json:"metric"`
Histograms []SampleHistogramPair `json:"histograms"`
}{
Metric: ss.Metric,
Histograms: ss.Histograms,
}
return json.Marshal(&v)
} else {
v := struct {
Metric Metric `json:"metric"`
Values []SamplePair `json:"values"`
}{
Metric: ss.Metric,
Values: ss.Values,
}
return json.Marshal(&v)
}
}
func (Matrix) Type() ValueType { return ValMatrix }
func (Vector) Type() ValueType { return ValVector }
func (*Scalar) Type() ValueType { return ValScalar }
func (*String) Type() ValueType { return ValString }
func (ss *SampleStream) UnmarshalJSON(b []byte) error {
v := struct {
Metric Metric `json:"metric"`
Values []SamplePair `json:"values"`
Histograms []SampleHistogramPair `json:"histograms"`
}{
Metric: ss.Metric,
Values: ss.Values,
Histograms: ss.Histograms,
}
type ValueType int
const (
ValNone ValueType = iota
ValScalar
ValVector
ValMatrix
ValString
)
// MarshalJSON implements json.Marshaler.
func (et ValueType) MarshalJSON() ([]byte, error) {
return json.Marshal(et.String())
}
func (et *ValueType) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
if err := json.Unmarshal(b, &v); err != nil {
return err
}
switch s {
case "<ValNone>":
*et = ValNone
case "scalar":
*et = ValScalar
case "vector":
*et = ValVector
case "matrix":
*et = ValMatrix
case "string":
*et = ValString
default:
return fmt.Errorf("unknown value type %q", s)
}
return nil
}
func (e ValueType) String() string {
switch e {
case ValNone:
return "<ValNone>"
case ValScalar:
return "scalar"
case ValVector:
return "vector"
case ValMatrix:
return "matrix"
case ValString:
return "string"
}
panic("ValueType.String: unhandled value type")
ss.Metric = v.Metric
ss.Values = v.Values
ss.Histograms = v.Histograms
return nil
}
// Scalar is a scalar value evaluated at the set timestamp.

View File

@ -0,0 +1,100 @@
// Copyright 2013 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package model
import (
"encoding/json"
"fmt"
"math"
"strconv"
)
var (
// ZeroSamplePair is the pseudo zero-value of SamplePair used to signal a
// non-existing sample pair. It is a SamplePair with timestamp Earliest and
// value 0.0. Note that the natural zero value of SamplePair has a timestamp
// of 0, which is possible to appear in a real SamplePair and thus not
// suitable to signal a non-existing SamplePair.
ZeroSamplePair = SamplePair{Timestamp: Earliest}
)
// A SampleValue is a representation of a value for a given sample at a given
// time.
type SampleValue float64
// MarshalJSON implements json.Marshaler.
func (v SampleValue) MarshalJSON() ([]byte, error) {
return json.Marshal(v.String())
}
// UnmarshalJSON implements json.Unmarshaler.
func (v *SampleValue) UnmarshalJSON(b []byte) error {
if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
return fmt.Errorf("sample value must be a quoted string")
}
f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64)
if err != nil {
return err
}
*v = SampleValue(f)
return nil
}
// Equal returns true if the value of v and o is equal or if both are NaN. Note
// that v==o is false if both are NaN. If you want the conventional float
// behavior, use == to compare two SampleValues.
func (v SampleValue) Equal(o SampleValue) bool {
if v == o {
return true
}
return math.IsNaN(float64(v)) && math.IsNaN(float64(o))
}
func (v SampleValue) String() string {
return strconv.FormatFloat(float64(v), 'f', -1, 64)
}
// SamplePair pairs a SampleValue with a Timestamp.
type SamplePair struct {
Timestamp Time
Value SampleValue
}
func (s SamplePair) MarshalJSON() ([]byte, error) {
t, err := json.Marshal(s.Timestamp)
if err != nil {
return nil, err
}
v, err := json.Marshal(s.Value)
if err != nil {
return nil, err
}
return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil
}
// UnmarshalJSON implements json.Unmarshaler.
func (s *SamplePair) UnmarshalJSON(b []byte) error {
v := [...]json.Unmarshaler{&s.Timestamp, &s.Value}
return json.Unmarshal(b, &v)
}
// Equal returns true if this SamplePair and o have equal Values and equal
// Timestamps. The semantics of Value equality is defined by SampleValue.Equal.
func (s *SamplePair) Equal(o *SamplePair) bool {
return s == o || (s.Value.Equal(o.Value) && s.Timestamp.Equal(o.Timestamp))
}
func (s SamplePair) String() string {
return fmt.Sprintf("%s @[%s]", s.Value, s.Timestamp)
}

View File

@ -0,0 +1,178 @@
// Copyright 2013 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package model
import (
"encoding/json"
"fmt"
"strconv"
"strings"
)
type FloatString float64
func (v FloatString) String() string {
return strconv.FormatFloat(float64(v), 'f', -1, 64)
}
func (v FloatString) MarshalJSON() ([]byte, error) {
return json.Marshal(v.String())
}
func (v *FloatString) UnmarshalJSON(b []byte) error {
if len(b) < 2 || b[0] != '"' || b[len(b)-1] != '"' {
return fmt.Errorf("float value must be a quoted string")
}
f, err := strconv.ParseFloat(string(b[1:len(b)-1]), 64)
if err != nil {
return err
}
*v = FloatString(f)
return nil
}
type HistogramBucket struct {
Boundaries int32
Lower FloatString
Upper FloatString
Count FloatString
}
func (s HistogramBucket) MarshalJSON() ([]byte, error) {
b, err := json.Marshal(s.Boundaries)
if err != nil {
return nil, err
}
l, err := json.Marshal(s.Lower)
if err != nil {
return nil, err
}
u, err := json.Marshal(s.Upper)
if err != nil {
return nil, err
}
c, err := json.Marshal(s.Count)
if err != nil {
return nil, err
}
return []byte(fmt.Sprintf("[%s,%s,%s,%s]", b, l, u, c)), nil
}
func (s *HistogramBucket) UnmarshalJSON(buf []byte) error {
tmp := []interface{}{&s.Boundaries, &s.Lower, &s.Upper, &s.Count}
wantLen := len(tmp)
if err := json.Unmarshal(buf, &tmp); err != nil {
return err
}
if gotLen := len(tmp); gotLen != wantLen {
return fmt.Errorf("wrong number of fields: %d != %d", gotLen, wantLen)
}
return nil
}
func (s *HistogramBucket) Equal(o *HistogramBucket) bool {
return s == o || (s.Boundaries == o.Boundaries && s.Lower == o.Lower && s.Upper == o.Upper && s.Count == o.Count)
}
func (b HistogramBucket) String() string {
var sb strings.Builder
lowerInclusive := b.Boundaries == 1 || b.Boundaries == 3
upperInclusive := b.Boundaries == 0 || b.Boundaries == 3
if lowerInclusive {
sb.WriteRune('[')
} else {
sb.WriteRune('(')
}
fmt.Fprintf(&sb, "%g,%g", b.Lower, b.Upper)
if upperInclusive {
sb.WriteRune(']')
} else {
sb.WriteRune(')')
}
fmt.Fprintf(&sb, ":%v", b.Count)
return sb.String()
}
type HistogramBuckets []*HistogramBucket
func (s HistogramBuckets) Equal(o HistogramBuckets) bool {
if len(s) != len(o) {
return false
}
for i, bucket := range s {
if !bucket.Equal(o[i]) {
return false
}
}
return true
}
type SampleHistogram struct {
Count FloatString `json:"count"`
Sum FloatString `json:"sum"`
Buckets HistogramBuckets `json:"buckets"`
}
func (s SampleHistogram) String() string {
return fmt.Sprintf("Count: %f, Sum: %f, Buckets: %v", s.Count, s.Sum, s.Buckets)
}
func (s *SampleHistogram) Equal(o *SampleHistogram) bool {
return s == o || (s.Count == o.Count && s.Sum == o.Sum && s.Buckets.Equal(o.Buckets))
}
type SampleHistogramPair struct {
Timestamp Time
// Histogram should never be nil, it's only stored as pointer for efficiency.
Histogram *SampleHistogram
}
func (s SampleHistogramPair) MarshalJSON() ([]byte, error) {
if s.Histogram == nil {
return nil, fmt.Errorf("histogram is nil")
}
t, err := json.Marshal(s.Timestamp)
if err != nil {
return nil, err
}
v, err := json.Marshal(s.Histogram)
if err != nil {
return nil, err
}
return []byte(fmt.Sprintf("[%s,%s]", t, v)), nil
}
func (s *SampleHistogramPair) UnmarshalJSON(buf []byte) error {
tmp := []interface{}{&s.Timestamp, &s.Histogram}
wantLen := len(tmp)
if err := json.Unmarshal(buf, &tmp); err != nil {
return err
}
if gotLen := len(tmp); gotLen != wantLen {
return fmt.Errorf("wrong number of fields: %d != %d", gotLen, wantLen)
}
if s.Histogram == nil {
return fmt.Errorf("histogram is null")
}
return nil
}
func (s SampleHistogramPair) String() string {
return fmt.Sprintf("%s @[%s]", s.Histogram, s.Timestamp)
}
func (s *SampleHistogramPair) Equal(o *SampleHistogramPair) bool {
return s == o || (s.Histogram.Equal(o.Histogram) && s.Timestamp.Equal(o.Timestamp))
}

View File

@ -0,0 +1,83 @@
// Copyright 2013 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package model
import (
"encoding/json"
"fmt"
)
// Value is a generic interface for values resulting from a query evaluation.
type Value interface {
Type() ValueType
String() string
}
func (Matrix) Type() ValueType { return ValMatrix }
func (Vector) Type() ValueType { return ValVector }
func (*Scalar) Type() ValueType { return ValScalar }
func (*String) Type() ValueType { return ValString }
type ValueType int
const (
ValNone ValueType = iota
ValScalar
ValVector
ValMatrix
ValString
)
// MarshalJSON implements json.Marshaler.
func (et ValueType) MarshalJSON() ([]byte, error) {
return json.Marshal(et.String())
}
func (et *ValueType) UnmarshalJSON(b []byte) error {
var s string
if err := json.Unmarshal(b, &s); err != nil {
return err
}
switch s {
case "<ValNone>":
*et = ValNone
case "scalar":
*et = ValScalar
case "vector":
*et = ValVector
case "matrix":
*et = ValMatrix
case "string":
*et = ValString
default:
return fmt.Errorf("unknown value type %q", s)
}
return nil
}
func (e ValueType) String() string {
switch e {
case ValNone:
return "<ValNone>"
case ValScalar:
return "scalar"
case ValVector:
return "vector"
case ValMatrix:
return "matrix"
case ValString:
return "string"
}
panic("ValueType.String: unhandled value type")
}

View File

@ -55,19 +55,22 @@ ifneq ($(shell which gotestsum),)
endif
endif
PROMU_VERSION ?= 0.13.0
PROMU_VERSION ?= 0.14.0
PROMU_URL := https://github.com/prometheus/promu/releases/download/v$(PROMU_VERSION)/promu-$(PROMU_VERSION).$(GO_BUILD_PLATFORM).tar.gz
SKIP_GOLANGCI_LINT :=
GOLANGCI_LINT :=
GOLANGCI_LINT_OPTS ?=
GOLANGCI_LINT_VERSION ?= v1.45.2
GOLANGCI_LINT_VERSION ?= v1.51.2
# golangci-lint only supports linux, darwin and windows platforms on i386/amd64.
# windows isn't included here because of the path separator being different.
ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux darwin))
ifeq ($(GOHOSTARCH),$(filter $(GOHOSTARCH),amd64 i386))
# If we're in CI and there is an Actions file, that means the linter
# is being run in Actions, so we don't need to run it here.
ifeq (,$(CIRCLE_JOB))
ifneq (,$(SKIP_GOLANGCI_LINT))
GOLANGCI_LINT :=
else ifeq (,$(CIRCLE_JOB))
GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint
else ifeq (,$(wildcard .github/workflows/golangci-lint.yml))
GOLANGCI_LINT := $(FIRST_GOPATH)/bin/golangci-lint
@ -88,6 +91,8 @@ BUILD_DOCKER_ARCHS = $(addprefix common-docker-,$(DOCKER_ARCHS))
PUBLISH_DOCKER_ARCHS = $(addprefix common-docker-publish-,$(DOCKER_ARCHS))
TAG_DOCKER_ARCHS = $(addprefix common-docker-tag-latest-,$(DOCKER_ARCHS))
SANITIZED_DOCKER_IMAGE_TAG := $(subst +,-,$(DOCKER_IMAGE_TAG))
ifeq ($(GOHOSTARCH),amd64)
ifeq ($(GOHOSTOS),$(filter $(GOHOSTOS),linux freebsd darwin windows))
# Only supported on amd64
@ -202,7 +207,7 @@ common-tarball: promu
.PHONY: common-docker $(BUILD_DOCKER_ARCHS)
common-docker: $(BUILD_DOCKER_ARCHS)
$(BUILD_DOCKER_ARCHS): common-docker-%:
docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" \
docker build -t "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" \
-f $(DOCKERFILE_PATH) \
--build-arg ARCH="$*" \
--build-arg OS="linux" \
@ -211,19 +216,19 @@ $(BUILD_DOCKER_ARCHS): common-docker-%:
.PHONY: common-docker-publish $(PUBLISH_DOCKER_ARCHS)
common-docker-publish: $(PUBLISH_DOCKER_ARCHS)
$(PUBLISH_DOCKER_ARCHS): common-docker-publish-%:
docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)"
docker push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)"
DOCKER_MAJOR_VERSION_TAG = $(firstword $(subst ., ,$(shell cat VERSION)))
.PHONY: common-docker-tag-latest $(TAG_DOCKER_ARCHS)
common-docker-tag-latest: $(TAG_DOCKER_ARCHS)
$(TAG_DOCKER_ARCHS): common-docker-tag-latest-%:
docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest"
docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)"
docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:latest"
docker tag "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:$(SANITIZED_DOCKER_IMAGE_TAG)" "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$*:v$(DOCKER_MAJOR_VERSION_TAG)"
.PHONY: common-docker-manifest
common-docker-manifest:
DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)" $(foreach ARCH,$(DOCKER_ARCHS),$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$(ARCH):$(DOCKER_IMAGE_TAG))
DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)"
DOCKER_CLI_EXPERIMENTAL=enabled docker manifest create -a "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)" $(foreach ARCH,$(DOCKER_ARCHS),$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME)-linux-$(ARCH):$(SANITIZED_DOCKER_IMAGE_TAG))
DOCKER_CLI_EXPERIMENTAL=enabled docker manifest push "$(DOCKER_REPO)/$(DOCKER_IMAGE_NAME):$(SANITIZED_DOCKER_IMAGE_TAG)"
.PHONY: promu
promu: $(PROMU)

View File

@ -380,6 +380,42 @@ func parseCPUInfoMips(info []byte) ([]CPUInfo, error) {
return cpuinfo, nil
}
func parseCPUInfoLoong(info []byte) ([]CPUInfo, error) {
scanner := bufio.NewScanner(bytes.NewReader(info))
// find the first "processor" line
firstLine := firstNonEmptyLine(scanner)
if !strings.HasPrefix(firstLine, "system type") || !strings.Contains(firstLine, ":") {
return nil, errors.New("invalid cpuinfo file: " + firstLine)
}
field := strings.SplitN(firstLine, ": ", 2)
cpuinfo := []CPUInfo{}
systemType := field[1]
i := 0
for scanner.Scan() {
line := scanner.Text()
if !strings.Contains(line, ":") {
continue
}
field := strings.SplitN(line, ": ", 2)
switch strings.TrimSpace(field[0]) {
case "processor":
v, err := strconv.ParseUint(field[1], 0, 32)
if err != nil {
return nil, err
}
i = int(v)
cpuinfo = append(cpuinfo, CPUInfo{}) // start of the next processor
cpuinfo[i].Processor = uint(v)
cpuinfo[i].VendorID = systemType
case "CPU Family":
cpuinfo[i].CPUFamily = field[1]
case "Model Name":
cpuinfo[i].ModelName = field[1]
}
}
return cpuinfo, nil
}
func parseCPUInfoPPC(info []byte) ([]CPUInfo, error) {
scanner := bufio.NewScanner(bytes.NewReader(info))

View File

@ -0,0 +1,19 @@
// Copyright 2022 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build linux
// +build linux
package procfs
var parseCPUInfo = parseCPUInfoLoong

View File

@ -11,8 +11,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build linux && !386 && !amd64 && !arm && !arm64 && !mips && !mips64 && !mips64le && !mipsle && !ppc64 && !ppc64le && !riscv64 && !s390x
// +build linux,!386,!amd64,!arm,!arm64,!mips,!mips64,!mips64le,!mipsle,!ppc64,!ppc64le,!riscv64,!s390x
//go:build linux && !386 && !amd64 && !arm && !arm64 && !loong64 && !mips && !mips64 && !mips64le && !mipsle && !ppc64 && !ppc64le && !riscv64 && !s390x
// +build linux,!386,!amd64,!arm,!arm64,!loong64,!mips,!mips64,!mips64le,!mipsle,!ppc64,!ppc64le,!riscv64,!s390x
package procfs

View File

@ -16,30 +16,29 @@
//
// Example:
//
// package main
// package main
//
// import (
// "fmt"
// "log"
// import (
// "fmt"
// "log"
//
// "github.com/prometheus/procfs"
// )
// "github.com/prometheus/procfs"
// )
//
// func main() {
// p, err := procfs.Self()
// if err != nil {
// log.Fatalf("could not get process: %s", err)
// }
// func main() {
// p, err := procfs.Self()
// if err != nil {
// log.Fatalf("could not get process: %s", err)
// }
//
// stat, err := p.Stat()
// if err != nil {
// log.Fatalf("could not get process stat: %s", err)
// }
//
// fmt.Printf("command: %s\n", stat.Comm)
// fmt.Printf("cpu time: %fs\n", stat.CPUTime())
// fmt.Printf("vsize: %dB\n", stat.VirtualMemory())
// fmt.Printf("rss: %dB\n", stat.ResidentMemory())
// }
// stat, err := p.Stat()
// if err != nil {
// log.Fatalf("could not get process stat: %s", err)
// }
//
// fmt.Printf("command: %s\n", stat.Comm)
// fmt.Printf("cpu time: %fs\n", stat.CPUTime())
// fmt.Printf("vsize: %dB\n", stat.VirtualMemory())
// fmt.Printf("rss: %dB\n", stat.ResidentMemory())
// }
package procfs

View File

@ -21,6 +21,7 @@ import (
// kernel data structures.
type FS struct {
proc fs.FS
real bool
}
// DefaultMountPoint is the common mount point of the proc filesystem.
@ -39,5 +40,11 @@ func NewFS(mountPoint string) (FS, error) {
if err != nil {
return FS{}, err
}
return FS{fs}, nil
real, err := isRealProc(mountPoint)
if err != nil {
return FS{}, err
}
return FS{fs, real}, nil
}

View File

@ -0,0 +1,23 @@
// Copyright 2018 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build netbsd || openbsd || solaris || windows
// +build netbsd openbsd solaris windows
package procfs
// isRealProc returns true on architectures that don't have a Type argument
// in their Statfs_t struct
func isRealProc(mountPoint string) (bool, error) {
return true, nil
}

View File

@ -0,0 +1,33 @@
// Copyright 2018 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build !netbsd && !openbsd && !solaris && !windows
// +build !netbsd,!openbsd,!solaris,!windows
package procfs
import (
"syscall"
)
// isRealProc determines whether supplied mountpoint is really a proc filesystem.
func isRealProc(mountPoint string) (bool, error) {
stat := syscall.Statfs_t{}
err := syscall.Statfs(mountPoint, &stat)
if err != nil {
return false, err
}
// 0x9fa0 is PROC_SUPER_MAGIC: https://elixir.bootlin.com/linux/v6.1/source/include/uapi/linux/magic.h#L87
return stat.Type == 0x9fa0, nil
}

View File

@ -64,6 +64,21 @@ func ParsePInt64s(ss []string) ([]*int64, error) {
return us, nil
}
// Parses a uint64 from given hex in string.
func ParseHexUint64s(ss []string) ([]*uint64, error) {
us := make([]*uint64, 0, len(ss))
for _, s := range ss {
u, err := strconv.ParseUint(s, 16, 64)
if err != nil {
return nil, err
}
us = append(us, &u)
}
return us, nil
}
// ReadUintFromFile reads a file and attempts to parse a uint64 from it.
func ReadUintFromFile(path string) (uint64, error) {
data, err := os.ReadFile(path)

View File

@ -186,6 +186,8 @@ type NFSOperationStats struct {
CumulativeTotalResponseMilliseconds uint64
// Duration from when a request was enqueued to when it was completely handled.
CumulativeTotalRequestMilliseconds uint64
// The average time from the point the client sends RPC requests until it receives the response.
AverageRTTMilliseconds float64
// The count of operations that complete with tk_status < 0. These statuses usually indicate error conditions.
Errors uint64
}
@ -284,7 +286,8 @@ func parseMountStats(r io.Reader) ([]*Mount, error) {
}
// parseMount parses an entry in /proc/[pid]/mountstats in the format:
// device [device] mounted on [mount] with fstype [type]
//
// device [device] mounted on [mount] with fstype [type]
func parseMount(ss []string) (*Mount, error) {
if len(ss) < deviceEntryLen {
return nil, fmt.Errorf("invalid device entry: %v", ss)
@ -533,7 +536,6 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) {
ns = append(ns, n)
}
opStats := NFSOperationStats{
Operation: strings.TrimSuffix(ss[0], ":"),
Requests: ns[0],
@ -545,6 +547,9 @@ func parseNFSOperationStats(s *bufio.Scanner) ([]NFSOperationStats, error) {
CumulativeTotalResponseMilliseconds: ns[6],
CumulativeTotalRequestMilliseconds: ns[7],
}
if ns[0] != 0 {
opStats.AverageRTTMilliseconds = float64(ns[6]) / float64(ns[0])
}
if len(ns) > 8 {
opStats.Errors = ns[8]

View File

@ -18,7 +18,6 @@ import (
"bytes"
"fmt"
"io"
"strconv"
"strings"
"github.com/prometheus/procfs/internal/util"
@ -28,9 +27,13 @@ import (
// and contains netfilter conntrack statistics at one CPU core.
type ConntrackStatEntry struct {
Entries uint64
Searched uint64
Found uint64
New uint64
Invalid uint64
Ignore uint64
Delete uint64
DeleteList uint64
Insert uint64
InsertFailed uint64
Drop uint64
@ -81,73 +84,34 @@ func parseConntrackStat(r io.Reader) ([]ConntrackStatEntry, error) {
// Parses a ConntrackStatEntry from given array of fields.
func parseConntrackStatEntry(fields []string) (*ConntrackStatEntry, error) {
if len(fields) != 17 {
return nil, fmt.Errorf("invalid conntrackstat entry, missing fields")
}
entry := &ConntrackStatEntry{}
entries, err := parseConntrackStatField(fields[0])
entries, err := util.ParseHexUint64s(fields)
if err != nil {
return nil, err
return nil, fmt.Errorf("invalid conntrackstat entry, couldn't parse fields: %s", err)
}
entry.Entries = entries
found, err := parseConntrackStatField(fields[2])
if err != nil {
return nil, err
numEntries := len(entries)
if numEntries < 16 || numEntries > 17 {
return nil, fmt.Errorf("invalid conntrackstat entry, invalid number of fields: %d", numEntries)
}
entry.Found = found
invalid, err := parseConntrackStatField(fields[4])
if err != nil {
return nil, err
stats := &ConntrackStatEntry{
Entries: *entries[0],
Searched: *entries[1],
Found: *entries[2],
New: *entries[3],
Invalid: *entries[4],
Ignore: *entries[5],
Delete: *entries[6],
DeleteList: *entries[7],
Insert: *entries[8],
InsertFailed: *entries[9],
Drop: *entries[10],
EarlyDrop: *entries[11],
}
entry.Invalid = invalid
ignore, err := parseConntrackStatField(fields[5])
if err != nil {
return nil, err
// Ignore missing search_restart on Linux < 2.6.35.
if numEntries == 17 {
stats.SearchRestart = *entries[16]
}
entry.Ignore = ignore
insert, err := parseConntrackStatField(fields[8])
if err != nil {
return nil, err
}
entry.Insert = insert
insertFailed, err := parseConntrackStatField(fields[9])
if err != nil {
return nil, err
}
entry.InsertFailed = insertFailed
drop, err := parseConntrackStatField(fields[10])
if err != nil {
return nil, err
}
entry.Drop = drop
earlyDrop, err := parseConntrackStatField(fields[11])
if err != nil {
return nil, err
}
entry.EarlyDrop = earlyDrop
searchRestart, err := parseConntrackStatField(fields[16])
if err != nil {
return nil, err
}
entry.SearchRestart = searchRestart
return entry, nil
}
// Parses a uint64 from given hex in string.
func parseConntrackStatField(field string) (uint64, error) {
val, err := strconv.ParseUint(field, 16, 64)
if err != nil {
return 0, fmt.Errorf("couldn't parse %q field: %w", field, err)
}
return val, err
return stats, nil
}

View File

@ -27,8 +27,9 @@ import (
// For the proc file format details,
// See:
// * Linux 2.6.23 https://elixir.bootlin.com/linux/v2.6.23/source/net/core/dev.c#L2343
// * Linux 4.17 https://elixir.bootlin.com/linux/v4.17/source/net/core/net-procfs.c#L162
// and https://elixir.bootlin.com/linux/v4.17/source/include/linux/netdevice.h#L2810.
// * Linux 2.6.39 https://elixir.bootlin.com/linux/v2.6.39/source/net/core/dev.c#L4086
// * Linux 4.18 https://elixir.bootlin.com/linux/v4.18/source/net/core/net-procfs.c#L162
// * Linux 5.14 https://elixir.bootlin.com/linux/v5.14/source/net/core/net-procfs.c#L169
// SoftnetStat contains a single row of data from /proc/net/softnet_stat.
type SoftnetStat struct {
@ -38,6 +39,18 @@ type SoftnetStat struct {
Dropped uint32
// Number of times processing packets ran out of quota.
TimeSqueezed uint32
// Number of collision occur while obtaining device lock while transmitting.
CPUCollision uint32
// Number of times cpu woken up received_rps.
ReceivedRps uint32
// number of times flow limit has been reached.
FlowLimitCount uint32
// Softnet backlog status.
SoftnetBacklogLen uint32
// CPU id owning this softnet_data.
Index uint32
// softnet_data's Width.
Width int
}
var softNetProcFile = "net/softnet_stat"
@ -63,25 +76,65 @@ func parseSoftnet(r io.Reader) ([]SoftnetStat, error) {
s := bufio.NewScanner(r)
var stats []SoftnetStat
cpuIndex := 0
for s.Scan() {
columns := strings.Fields(s.Text())
width := len(columns)
softnetStat := SoftnetStat{}
if width < minColumns {
return nil, fmt.Errorf("%d columns were detected, but at least %d were expected", width, minColumns)
}
// We only parse the first three columns at the moment.
us, err := parseHexUint32s(columns[0:3])
if err != nil {
return nil, err
// Linux 2.6.23 https://elixir.bootlin.com/linux/v2.6.23/source/net/core/dev.c#L2347
if width >= minColumns {
us, err := parseHexUint32s(columns[0:9])
if err != nil {
return nil, err
}
softnetStat.Processed = us[0]
softnetStat.Dropped = us[1]
softnetStat.TimeSqueezed = us[2]
softnetStat.CPUCollision = us[8]
}
stats = append(stats, SoftnetStat{
Processed: us[0],
Dropped: us[1],
TimeSqueezed: us[2],
})
// Linux 2.6.39 https://elixir.bootlin.com/linux/v2.6.39/source/net/core/dev.c#L4086
if width >= 10 {
us, err := parseHexUint32s(columns[9:10])
if err != nil {
return nil, err
}
softnetStat.ReceivedRps = us[0]
}
// Linux 4.18 https://elixir.bootlin.com/linux/v4.18/source/net/core/net-procfs.c#L162
if width >= 11 {
us, err := parseHexUint32s(columns[10:11])
if err != nil {
return nil, err
}
softnetStat.FlowLimitCount = us[0]
}
// Linux 5.14 https://elixir.bootlin.com/linux/v5.14/source/net/core/net-procfs.c#L169
if width >= 13 {
us, err := parseHexUint32s(columns[11:13])
if err != nil {
return nil, err
}
softnetStat.SoftnetBacklogLen = us[0]
softnetStat.Index = us[1]
} else {
// For older kernels, create the Index based on the scan line number.
softnetStat.Index = uint32(cpuIndex)
}
softnetStat.Width = width
stats = append(stats, softnetStat)
cpuIndex++
}
return stats, nil

182
src/vendor/github.com/prometheus/procfs/net_wireless.go generated vendored Normal file
View File

@ -0,0 +1,182 @@
// Copyright 2023 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package procfs
import (
"bufio"
"bytes"
"fmt"
"io"
"strconv"
"strings"
"github.com/prometheus/procfs/internal/util"
)
// Wireless models the content of /proc/net/wireless.
type Wireless struct {
Name string
// Status is the current 4-digit hex value status of the interface.
Status uint64
// QualityLink is the link quality.
QualityLink int
// QualityLevel is the signal gain (dBm).
QualityLevel int
// QualityNoise is the signal noise baseline (dBm).
QualityNoise int
// DiscardedNwid is the number of discarded packets with wrong nwid/essid.
DiscardedNwid int
// DiscardedCrypt is the number of discarded packets with wrong code/decode (WEP).
DiscardedCrypt int
// DiscardedFrag is the number of discarded packets that can't perform MAC reassembly.
DiscardedFrag int
// DiscardedRetry is the number of discarded packets that reached max MAC retries.
DiscardedRetry int
// DiscardedMisc is the number of discarded packets for other reasons.
DiscardedMisc int
// MissedBeacon is the number of missed beacons/superframe.
MissedBeacon int
}
// Wireless returns kernel wireless statistics.
func (fs FS) Wireless() ([]*Wireless, error) {
b, err := util.ReadFileNoStat(fs.proc.Path("net/wireless"))
if err != nil {
return nil, err
}
m, err := parseWireless(bytes.NewReader(b))
if err != nil {
return nil, fmt.Errorf("failed to parse wireless: %w", err)
}
return m, nil
}
// parseWireless parses the contents of /proc/net/wireless.
/*
Inter-| sta-| Quality | Discarded packets | Missed | WE
face | tus | link level noise | nwid crypt frag retry misc | beacon | 22
eth1: 0000 5. -256. -10. 0 1 0 3 0 0
eth2: 0000 5. -256. -20. 0 2 0 4 0 0
*/
func parseWireless(r io.Reader) ([]*Wireless, error) {
var (
interfaces []*Wireless
scanner = bufio.NewScanner(r)
)
for n := 0; scanner.Scan(); n++ {
// Skip the 2 header lines.
if n < 2 {
continue
}
line := scanner.Text()
parts := strings.Split(line, ":")
if len(parts) != 2 {
return nil, fmt.Errorf("expected 2 parts after splitting line by ':', got %d for line %q", len(parts), line)
}
name := strings.TrimSpace(parts[0])
stats := strings.Fields(parts[1])
if len(stats) < 10 {
return nil, fmt.Errorf("invalid number of fields in line %d, expected at least 10, got %d: %q", n, len(stats), line)
}
status, err := strconv.ParseUint(stats[0], 16, 16)
if err != nil {
return nil, fmt.Errorf("invalid status in line %d: %q", n, line)
}
qlink, err := strconv.Atoi(strings.TrimSuffix(stats[1], "."))
if err != nil {
return nil, fmt.Errorf("failed to parse Quality:link as integer %q: %w", qlink, err)
}
qlevel, err := strconv.Atoi(strings.TrimSuffix(stats[2], "."))
if err != nil {
return nil, fmt.Errorf("failed to parse Quality:level as integer %q: %w", qlevel, err)
}
qnoise, err := strconv.Atoi(strings.TrimSuffix(stats[3], "."))
if err != nil {
return nil, fmt.Errorf("failed to parse Quality:noise as integer %q: %w", qnoise, err)
}
dnwid, err := strconv.Atoi(stats[4])
if err != nil {
return nil, fmt.Errorf("failed to parse Discarded:nwid as integer %q: %w", dnwid, err)
}
dcrypt, err := strconv.Atoi(stats[5])
if err != nil {
return nil, fmt.Errorf("failed to parse Discarded:crypt as integer %q: %w", dcrypt, err)
}
dfrag, err := strconv.Atoi(stats[6])
if err != nil {
return nil, fmt.Errorf("failed to parse Discarded:frag as integer %q: %w", dfrag, err)
}
dretry, err := strconv.Atoi(stats[7])
if err != nil {
return nil, fmt.Errorf("failed to parse Discarded:retry as integer %q: %w", dretry, err)
}
dmisc, err := strconv.Atoi(stats[8])
if err != nil {
return nil, fmt.Errorf("failed to parse Discarded:misc as integer %q: %w", dmisc, err)
}
mbeacon, err := strconv.Atoi(stats[9])
if err != nil {
return nil, fmt.Errorf("failed to parse Missed:beacon as integer %q: %w", mbeacon, err)
}
w := &Wireless{
Name: name,
Status: status,
QualityLink: qlink,
QualityLevel: qlevel,
QualityNoise: qnoise,
DiscardedNwid: dnwid,
DiscardedCrypt: dcrypt,
DiscardedFrag: dfrag,
DiscardedRetry: dretry,
DiscardedMisc: dmisc,
MissedBeacon: mbeacon,
}
interfaces = append(interfaces, w)
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("failed to scan /proc/net/wireless: %w", err)
}
return interfaces, nil
}

View File

@ -37,32 +37,46 @@ func (fs FS) NetStat() ([]NetStat, error) {
var netStatsTotal []NetStat
for _, filePath := range statFiles {
file, err := os.Open(filePath)
procNetstat, err := parseNetstat(filePath)
if err != nil {
return nil, err
}
procNetstat.Filename = filepath.Base(filePath)
netStatFile := NetStat{
Filename: filepath.Base(filePath),
Stats: make(map[string][]uint64),
}
scanner := bufio.NewScanner(file)
scanner.Scan()
// First string is always a header for stats
var headers []string
headers = append(headers, strings.Fields(scanner.Text())...)
// Other strings represent per-CPU counters
for scanner.Scan() {
for num, counter := range strings.Fields(scanner.Text()) {
value, err := strconv.ParseUint(counter, 16, 64)
if err != nil {
return nil, err
}
netStatFile.Stats[headers[num]] = append(netStatFile.Stats[headers[num]], value)
}
}
netStatsTotal = append(netStatsTotal, netStatFile)
netStatsTotal = append(netStatsTotal, procNetstat)
}
return netStatsTotal, nil
}
// parseNetstat parses the metrics from `/proc/net/stat/` file
// and returns a NetStat structure.
func parseNetstat(filePath string) (NetStat, error) {
netStat := NetStat{
Stats: make(map[string][]uint64),
}
file, err := os.Open(filePath)
if err != nil {
return netStat, err
}
defer file.Close()
scanner := bufio.NewScanner(file)
scanner.Scan()
// First string is always a header for stats
var headers []string
headers = append(headers, strings.Fields(scanner.Text())...)
// Other strings represent per-CPU counters
for scanner.Scan() {
for num, counter := range strings.Fields(scanner.Text()) {
value, err := strconv.ParseUint(counter, 16, 64)
if err != nil {
return NetStat{}, err
}
netStat.Stats[headers[num]] = append(netStat.Stats[headers[num]], value)
}
}
return netStat, nil
}

View File

@ -21,7 +21,6 @@ import (
"strconv"
"strings"
"github.com/prometheus/procfs/internal/fs"
"github.com/prometheus/procfs/internal/util"
)
@ -30,7 +29,7 @@ type Proc struct {
// The process ID.
PID int
fs fs.FS
fs FS
}
// Procs represents a list of Proc structs.
@ -92,7 +91,7 @@ func (fs FS) Proc(pid int) (Proc, error) {
if _, err := os.Stat(fs.proc.Path(strconv.Itoa(pid))); err != nil {
return Proc{}, err
}
return Proc{PID: pid, fs: fs.proc}, nil
return Proc{PID: pid, fs: fs}, nil
}
// AllProcs returns a list of all currently available processes.
@ -114,7 +113,7 @@ func (fs FS) AllProcs() (Procs, error) {
if err != nil {
continue
}
p = append(p, Proc{PID: int(pid), fs: fs.proc})
p = append(p, Proc{PID: int(pid), fs: fs})
}
return p, nil
@ -237,6 +236,19 @@ func (p Proc) FileDescriptorTargets() ([]string, error) {
// FileDescriptorsLen returns the number of currently open file descriptors of
// a process.
func (p Proc) FileDescriptorsLen() (int, error) {
// Use fast path if available (Linux v6.2): https://github.com/torvalds/linux/commit/f1f1f2569901
if p.fs.real {
stat, err := os.Stat(p.path("fd"))
if err != nil {
return 0, err
}
size := stat.Size()
if size > 0 {
return int(size), nil
}
}
fds, err := p.fileDescriptors()
if err != nil {
return 0, err
@ -285,7 +297,7 @@ func (p Proc) fileDescriptors() ([]string, error) {
}
func (p Proc) path(pa ...string) string {
return p.fs.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...)
return p.fs.proc.Path(append([]string{strconv.Itoa(p.PID)}, pa...)...)
}
// FileDescriptorsInfo retrieves information about all file descriptors of

View File

@ -23,7 +23,7 @@ import (
"github.com/prometheus/procfs/internal/util"
)
// Cgroup models one line from /proc/[pid]/cgroup. Each Cgroup struct describes the the placement of a PID inside a
// Cgroup models one line from /proc/[pid]/cgroup. Each Cgroup struct describes the placement of a PID inside a
// specific control hierarchy. The kernel has two cgroup APIs, v1 and v2. v1 has one hierarchy per available resource
// controller, while v2 has one unified hierarchy shared by all controllers. Regardless of v1 or v2, all hierarchies
// contain all running processes, so the question answerable with a Cgroup struct is 'where is this process in

View File

@ -0,0 +1,98 @@
// Copyright 2022 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package procfs
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"strconv"
"strings"
"github.com/prometheus/procfs/internal/util"
)
// Interrupt represents a single interrupt line.
type Interrupt struct {
// Info is the type of interrupt.
Info string
// Devices is the name of the device that is located at that IRQ
Devices string
// Values is the number of interrupts per CPU.
Values []string
}
// Interrupts models the content of /proc/interrupts. Key is the IRQ number.
// - https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/deployment_guide/s2-proc-interrupts
// - https://raspberrypi.stackexchange.com/questions/105802/explanation-of-proc-interrupts-output
type Interrupts map[string]Interrupt
// Interrupts creates a new instance from a given Proc instance.
func (p Proc) Interrupts() (Interrupts, error) {
data, err := util.ReadFileNoStat(p.path("interrupts"))
if err != nil {
return nil, err
}
return parseInterrupts(bytes.NewReader(data))
}
func parseInterrupts(r io.Reader) (Interrupts, error) {
var (
interrupts = Interrupts{}
scanner = bufio.NewScanner(r)
)
if !scanner.Scan() {
return nil, errors.New("interrupts empty")
}
cpuNum := len(strings.Fields(scanner.Text())) // one header per cpu
for scanner.Scan() {
parts := strings.Fields(scanner.Text())
if len(parts) == 0 { // skip empty lines
continue
}
if len(parts) < 2 {
return nil, fmt.Errorf("not enough fields in interrupts (expected at least 2 fields but got %d): %s", len(parts), parts)
}
intName := parts[0][:len(parts[0])-1] // remove trailing :
if len(parts) == 2 {
interrupts[intName] = Interrupt{
Info: "",
Devices: "",
Values: []string{
parts[1],
},
}
continue
}
intr := Interrupt{
Values: parts[1 : cpuNum+1],
}
if _, err := strconv.Atoi(intName); err == nil { // numeral interrupt
intr.Info = parts[cpuNum+1]
intr.Devices = strings.Join(parts[cpuNum+2:], " ")
} else {
intr.Info = strings.Join(parts[cpuNum+1:], " ")
}
interrupts[intName] = intr
}
return interrupts, scanner.Err()
}

View File

@ -33,139 +33,140 @@ type ProcNetstat struct {
}
type TcpExt struct { // nolint:revive
SyncookiesSent float64
SyncookiesRecv float64
SyncookiesFailed float64
EmbryonicRsts float64
PruneCalled float64
RcvPruned float64
OfoPruned float64
OutOfWindowIcmps float64
LockDroppedIcmps float64
ArpFilter float64
TW float64
TWRecycled float64
TWKilled float64
PAWSActive float64
PAWSEstab float64
DelayedACKs float64
DelayedACKLocked float64
DelayedACKLost float64
ListenOverflows float64
ListenDrops float64
TCPHPHits float64
TCPPureAcks float64
TCPHPAcks float64
TCPRenoRecovery float64
TCPSackRecovery float64
TCPSACKReneging float64
TCPSACKReorder float64
TCPRenoReorder float64
TCPTSReorder float64
TCPFullUndo float64
TCPPartialUndo float64
TCPDSACKUndo float64
TCPLossUndo float64
TCPLostRetransmit float64
TCPRenoFailures float64
TCPSackFailures float64
TCPLossFailures float64
TCPFastRetrans float64
TCPSlowStartRetrans float64
TCPTimeouts float64
TCPLossProbes float64
TCPLossProbeRecovery float64
TCPRenoRecoveryFail float64
TCPSackRecoveryFail float64
TCPRcvCollapsed float64
TCPDSACKOldSent float64
TCPDSACKOfoSent float64
TCPDSACKRecv float64
TCPDSACKOfoRecv float64
TCPAbortOnData float64
TCPAbortOnClose float64
TCPAbortOnMemory float64
TCPAbortOnTimeout float64
TCPAbortOnLinger float64
TCPAbortFailed float64
TCPMemoryPressures float64
TCPMemoryPressuresChrono float64
TCPSACKDiscard float64
TCPDSACKIgnoredOld float64
TCPDSACKIgnoredNoUndo float64
TCPSpuriousRTOs float64
TCPMD5NotFound float64
TCPMD5Unexpected float64
TCPMD5Failure float64
TCPSackShifted float64
TCPSackMerged float64
TCPSackShiftFallback float64
TCPBacklogDrop float64
PFMemallocDrop float64
TCPMinTTLDrop float64
TCPDeferAcceptDrop float64
IPReversePathFilter float64
TCPTimeWaitOverflow float64
TCPReqQFullDoCookies float64
TCPReqQFullDrop float64
TCPRetransFail float64
TCPRcvCoalesce float64
TCPOFOQueue float64
TCPOFODrop float64
TCPOFOMerge float64
TCPChallengeACK float64
TCPSYNChallenge float64
TCPFastOpenActive float64
TCPFastOpenActiveFail float64
TCPFastOpenPassive float64
TCPFastOpenPassiveFail float64
TCPFastOpenListenOverflow float64
TCPFastOpenCookieReqd float64
TCPFastOpenBlackhole float64
TCPSpuriousRtxHostQueues float64
BusyPollRxPackets float64
TCPAutoCorking float64
TCPFromZeroWindowAdv float64
TCPToZeroWindowAdv float64
TCPWantZeroWindowAdv float64
TCPSynRetrans float64
TCPOrigDataSent float64
TCPHystartTrainDetect float64
TCPHystartTrainCwnd float64
TCPHystartDelayDetect float64
TCPHystartDelayCwnd float64
TCPACKSkippedSynRecv float64
TCPACKSkippedPAWS float64
TCPACKSkippedSeq float64
TCPACKSkippedFinWait2 float64
TCPACKSkippedTimeWait float64
TCPACKSkippedChallenge float64
TCPWinProbe float64
TCPKeepAlive float64
TCPMTUPFail float64
TCPMTUPSuccess float64
TCPWqueueTooBig float64
SyncookiesSent *float64
SyncookiesRecv *float64
SyncookiesFailed *float64
EmbryonicRsts *float64
PruneCalled *float64
RcvPruned *float64
OfoPruned *float64
OutOfWindowIcmps *float64
LockDroppedIcmps *float64
ArpFilter *float64
TW *float64
TWRecycled *float64
TWKilled *float64
PAWSActive *float64
PAWSEstab *float64
DelayedACKs *float64
DelayedACKLocked *float64
DelayedACKLost *float64
ListenOverflows *float64
ListenDrops *float64
TCPHPHits *float64
TCPPureAcks *float64
TCPHPAcks *float64
TCPRenoRecovery *float64
TCPSackRecovery *float64
TCPSACKReneging *float64
TCPSACKReorder *float64
TCPRenoReorder *float64
TCPTSReorder *float64
TCPFullUndo *float64
TCPPartialUndo *float64
TCPDSACKUndo *float64
TCPLossUndo *float64
TCPLostRetransmit *float64
TCPRenoFailures *float64
TCPSackFailures *float64
TCPLossFailures *float64
TCPFastRetrans *float64
TCPSlowStartRetrans *float64
TCPTimeouts *float64
TCPLossProbes *float64
TCPLossProbeRecovery *float64
TCPRenoRecoveryFail *float64
TCPSackRecoveryFail *float64
TCPRcvCollapsed *float64
TCPDSACKOldSent *float64
TCPDSACKOfoSent *float64
TCPDSACKRecv *float64
TCPDSACKOfoRecv *float64
TCPAbortOnData *float64
TCPAbortOnClose *float64
TCPAbortOnMemory *float64
TCPAbortOnTimeout *float64
TCPAbortOnLinger *float64
TCPAbortFailed *float64
TCPMemoryPressures *float64
TCPMemoryPressuresChrono *float64
TCPSACKDiscard *float64
TCPDSACKIgnoredOld *float64
TCPDSACKIgnoredNoUndo *float64
TCPSpuriousRTOs *float64
TCPMD5NotFound *float64
TCPMD5Unexpected *float64
TCPMD5Failure *float64
TCPSackShifted *float64
TCPSackMerged *float64
TCPSackShiftFallback *float64
TCPBacklogDrop *float64
PFMemallocDrop *float64
TCPMinTTLDrop *float64
TCPDeferAcceptDrop *float64
IPReversePathFilter *float64
TCPTimeWaitOverflow *float64
TCPReqQFullDoCookies *float64
TCPReqQFullDrop *float64
TCPRetransFail *float64
TCPRcvCoalesce *float64
TCPRcvQDrop *float64
TCPOFOQueue *float64
TCPOFODrop *float64
TCPOFOMerge *float64
TCPChallengeACK *float64
TCPSYNChallenge *float64
TCPFastOpenActive *float64
TCPFastOpenActiveFail *float64
TCPFastOpenPassive *float64
TCPFastOpenPassiveFail *float64
TCPFastOpenListenOverflow *float64
TCPFastOpenCookieReqd *float64
TCPFastOpenBlackhole *float64
TCPSpuriousRtxHostQueues *float64
BusyPollRxPackets *float64
TCPAutoCorking *float64
TCPFromZeroWindowAdv *float64
TCPToZeroWindowAdv *float64
TCPWantZeroWindowAdv *float64
TCPSynRetrans *float64
TCPOrigDataSent *float64
TCPHystartTrainDetect *float64
TCPHystartTrainCwnd *float64
TCPHystartDelayDetect *float64
TCPHystartDelayCwnd *float64
TCPACKSkippedSynRecv *float64
TCPACKSkippedPAWS *float64
TCPACKSkippedSeq *float64
TCPACKSkippedFinWait2 *float64
TCPACKSkippedTimeWait *float64
TCPACKSkippedChallenge *float64
TCPWinProbe *float64
TCPKeepAlive *float64
TCPMTUPFail *float64
TCPMTUPSuccess *float64
TCPWqueueTooBig *float64
}
type IpExt struct { // nolint:revive
InNoRoutes float64
InTruncatedPkts float64
InMcastPkts float64
OutMcastPkts float64
InBcastPkts float64
OutBcastPkts float64
InOctets float64
OutOctets float64
InMcastOctets float64
OutMcastOctets float64
InBcastOctets float64
OutBcastOctets float64
InCsumErrors float64
InNoECTPkts float64
InECT1Pkts float64
InECT0Pkts float64
InCEPkts float64
ReasmOverlaps float64
InNoRoutes *float64
InTruncatedPkts *float64
InMcastPkts *float64
OutMcastPkts *float64
InBcastPkts *float64
OutBcastPkts *float64
InOctets *float64
OutOctets *float64
InMcastOctets *float64
OutMcastOctets *float64
InBcastOctets *float64
OutBcastOctets *float64
InCsumErrors *float64
InNoECTPkts *float64
InECT1Pkts *float64
InECT0Pkts *float64
InCEPkts *float64
ReasmOverlaps *float64
}
func (p Proc) Netstat() (ProcNetstat, error) {
@ -174,14 +175,14 @@ func (p Proc) Netstat() (ProcNetstat, error) {
if err != nil {
return ProcNetstat{PID: p.PID}, err
}
procNetstat, err := parseNetstat(bytes.NewReader(data), filename)
procNetstat, err := parseProcNetstat(bytes.NewReader(data), filename)
procNetstat.PID = p.PID
return procNetstat, err
}
// parseNetstat parses the metrics from proc/<pid>/net/netstat file
// parseProcNetstat parses the metrics from proc/<pid>/net/netstat file
// and returns a ProcNetstat structure.
func parseNetstat(r io.Reader, fileName string) (ProcNetstat, error) {
func parseProcNetstat(r io.Reader, fileName string) (ProcNetstat, error) {
var (
scanner = bufio.NewScanner(r)
procNetstat = ProcNetstat{}
@ -208,230 +209,232 @@ func parseNetstat(r io.Reader, fileName string) (ProcNetstat, error) {
case "TcpExt":
switch key {
case "SyncookiesSent":
procNetstat.TcpExt.SyncookiesSent = value
procNetstat.TcpExt.SyncookiesSent = &value
case "SyncookiesRecv":
procNetstat.TcpExt.SyncookiesRecv = value
procNetstat.TcpExt.SyncookiesRecv = &value
case "SyncookiesFailed":
procNetstat.TcpExt.SyncookiesFailed = value
procNetstat.TcpExt.SyncookiesFailed = &value
case "EmbryonicRsts":
procNetstat.TcpExt.EmbryonicRsts = value
procNetstat.TcpExt.EmbryonicRsts = &value
case "PruneCalled":
procNetstat.TcpExt.PruneCalled = value
procNetstat.TcpExt.PruneCalled = &value
case "RcvPruned":
procNetstat.TcpExt.RcvPruned = value
procNetstat.TcpExt.RcvPruned = &value
case "OfoPruned":
procNetstat.TcpExt.OfoPruned = value
procNetstat.TcpExt.OfoPruned = &value
case "OutOfWindowIcmps":
procNetstat.TcpExt.OutOfWindowIcmps = value
procNetstat.TcpExt.OutOfWindowIcmps = &value
case "LockDroppedIcmps":
procNetstat.TcpExt.LockDroppedIcmps = value
procNetstat.TcpExt.LockDroppedIcmps = &value
case "ArpFilter":
procNetstat.TcpExt.ArpFilter = value
procNetstat.TcpExt.ArpFilter = &value
case "TW":
procNetstat.TcpExt.TW = value
procNetstat.TcpExt.TW = &value
case "TWRecycled":
procNetstat.TcpExt.TWRecycled = value
procNetstat.TcpExt.TWRecycled = &value
case "TWKilled":
procNetstat.TcpExt.TWKilled = value
procNetstat.TcpExt.TWKilled = &value
case "PAWSActive":
procNetstat.TcpExt.PAWSActive = value
procNetstat.TcpExt.PAWSActive = &value
case "PAWSEstab":
procNetstat.TcpExt.PAWSEstab = value
procNetstat.TcpExt.PAWSEstab = &value
case "DelayedACKs":
procNetstat.TcpExt.DelayedACKs = value
procNetstat.TcpExt.DelayedACKs = &value
case "DelayedACKLocked":
procNetstat.TcpExt.DelayedACKLocked = value
procNetstat.TcpExt.DelayedACKLocked = &value
case "DelayedACKLost":
procNetstat.TcpExt.DelayedACKLost = value
procNetstat.TcpExt.DelayedACKLost = &value
case "ListenOverflows":
procNetstat.TcpExt.ListenOverflows = value
procNetstat.TcpExt.ListenOverflows = &value
case "ListenDrops":
procNetstat.TcpExt.ListenDrops = value
procNetstat.TcpExt.ListenDrops = &value
case "TCPHPHits":
procNetstat.TcpExt.TCPHPHits = value
procNetstat.TcpExt.TCPHPHits = &value
case "TCPPureAcks":
procNetstat.TcpExt.TCPPureAcks = value
procNetstat.TcpExt.TCPPureAcks = &value
case "TCPHPAcks":
procNetstat.TcpExt.TCPHPAcks = value
procNetstat.TcpExt.TCPHPAcks = &value
case "TCPRenoRecovery":
procNetstat.TcpExt.TCPRenoRecovery = value
procNetstat.TcpExt.TCPRenoRecovery = &value
case "TCPSackRecovery":
procNetstat.TcpExt.TCPSackRecovery = value
procNetstat.TcpExt.TCPSackRecovery = &value
case "TCPSACKReneging":
procNetstat.TcpExt.TCPSACKReneging = value
procNetstat.TcpExt.TCPSACKReneging = &value
case "TCPSACKReorder":
procNetstat.TcpExt.TCPSACKReorder = value
procNetstat.TcpExt.TCPSACKReorder = &value
case "TCPRenoReorder":
procNetstat.TcpExt.TCPRenoReorder = value
procNetstat.TcpExt.TCPRenoReorder = &value
case "TCPTSReorder":
procNetstat.TcpExt.TCPTSReorder = value
procNetstat.TcpExt.TCPTSReorder = &value
case "TCPFullUndo":
procNetstat.TcpExt.TCPFullUndo = value
procNetstat.TcpExt.TCPFullUndo = &value
case "TCPPartialUndo":
procNetstat.TcpExt.TCPPartialUndo = value
procNetstat.TcpExt.TCPPartialUndo = &value
case "TCPDSACKUndo":
procNetstat.TcpExt.TCPDSACKUndo = value
procNetstat.TcpExt.TCPDSACKUndo = &value
case "TCPLossUndo":
procNetstat.TcpExt.TCPLossUndo = value
procNetstat.TcpExt.TCPLossUndo = &value
case "TCPLostRetransmit":
procNetstat.TcpExt.TCPLostRetransmit = value
procNetstat.TcpExt.TCPLostRetransmit = &value
case "TCPRenoFailures":
procNetstat.TcpExt.TCPRenoFailures = value
procNetstat.TcpExt.TCPRenoFailures = &value
case "TCPSackFailures":
procNetstat.TcpExt.TCPSackFailures = value
procNetstat.TcpExt.TCPSackFailures = &value
case "TCPLossFailures":
procNetstat.TcpExt.TCPLossFailures = value
procNetstat.TcpExt.TCPLossFailures = &value
case "TCPFastRetrans":
procNetstat.TcpExt.TCPFastRetrans = value
procNetstat.TcpExt.TCPFastRetrans = &value
case "TCPSlowStartRetrans":
procNetstat.TcpExt.TCPSlowStartRetrans = value
procNetstat.TcpExt.TCPSlowStartRetrans = &value
case "TCPTimeouts":
procNetstat.TcpExt.TCPTimeouts = value
procNetstat.TcpExt.TCPTimeouts = &value
case "TCPLossProbes":
procNetstat.TcpExt.TCPLossProbes = value
procNetstat.TcpExt.TCPLossProbes = &value
case "TCPLossProbeRecovery":
procNetstat.TcpExt.TCPLossProbeRecovery = value
procNetstat.TcpExt.TCPLossProbeRecovery = &value
case "TCPRenoRecoveryFail":
procNetstat.TcpExt.TCPRenoRecoveryFail = value
procNetstat.TcpExt.TCPRenoRecoveryFail = &value
case "TCPSackRecoveryFail":
procNetstat.TcpExt.TCPSackRecoveryFail = value
procNetstat.TcpExt.TCPSackRecoveryFail = &value
case "TCPRcvCollapsed":
procNetstat.TcpExt.TCPRcvCollapsed = value
procNetstat.TcpExt.TCPRcvCollapsed = &value
case "TCPDSACKOldSent":
procNetstat.TcpExt.TCPDSACKOldSent = value
procNetstat.TcpExt.TCPDSACKOldSent = &value
case "TCPDSACKOfoSent":
procNetstat.TcpExt.TCPDSACKOfoSent = value
procNetstat.TcpExt.TCPDSACKOfoSent = &value
case "TCPDSACKRecv":
procNetstat.TcpExt.TCPDSACKRecv = value
procNetstat.TcpExt.TCPDSACKRecv = &value
case "TCPDSACKOfoRecv":
procNetstat.TcpExt.TCPDSACKOfoRecv = value
procNetstat.TcpExt.TCPDSACKOfoRecv = &value
case "TCPAbortOnData":
procNetstat.TcpExt.TCPAbortOnData = value
procNetstat.TcpExt.TCPAbortOnData = &value
case "TCPAbortOnClose":
procNetstat.TcpExt.TCPAbortOnClose = value
procNetstat.TcpExt.TCPAbortOnClose = &value
case "TCPDeferAcceptDrop":
procNetstat.TcpExt.TCPDeferAcceptDrop = value
procNetstat.TcpExt.TCPDeferAcceptDrop = &value
case "IPReversePathFilter":
procNetstat.TcpExt.IPReversePathFilter = value
procNetstat.TcpExt.IPReversePathFilter = &value
case "TCPTimeWaitOverflow":
procNetstat.TcpExt.TCPTimeWaitOverflow = value
procNetstat.TcpExt.TCPTimeWaitOverflow = &value
case "TCPReqQFullDoCookies":
procNetstat.TcpExt.TCPReqQFullDoCookies = value
procNetstat.TcpExt.TCPReqQFullDoCookies = &value
case "TCPReqQFullDrop":
procNetstat.TcpExt.TCPReqQFullDrop = value
procNetstat.TcpExt.TCPReqQFullDrop = &value
case "TCPRetransFail":
procNetstat.TcpExt.TCPRetransFail = value
procNetstat.TcpExt.TCPRetransFail = &value
case "TCPRcvCoalesce":
procNetstat.TcpExt.TCPRcvCoalesce = value
procNetstat.TcpExt.TCPRcvCoalesce = &value
case "TCPRcvQDrop":
procNetstat.TcpExt.TCPRcvQDrop = &value
case "TCPOFOQueue":
procNetstat.TcpExt.TCPOFOQueue = value
procNetstat.TcpExt.TCPOFOQueue = &value
case "TCPOFODrop":
procNetstat.TcpExt.TCPOFODrop = value
procNetstat.TcpExt.TCPOFODrop = &value
case "TCPOFOMerge":
procNetstat.TcpExt.TCPOFOMerge = value
procNetstat.TcpExt.TCPOFOMerge = &value
case "TCPChallengeACK":
procNetstat.TcpExt.TCPChallengeACK = value
procNetstat.TcpExt.TCPChallengeACK = &value
case "TCPSYNChallenge":
procNetstat.TcpExt.TCPSYNChallenge = value
procNetstat.TcpExt.TCPSYNChallenge = &value
case "TCPFastOpenActive":
procNetstat.TcpExt.TCPFastOpenActive = value
procNetstat.TcpExt.TCPFastOpenActive = &value
case "TCPFastOpenActiveFail":
procNetstat.TcpExt.TCPFastOpenActiveFail = value
procNetstat.TcpExt.TCPFastOpenActiveFail = &value
case "TCPFastOpenPassive":
procNetstat.TcpExt.TCPFastOpenPassive = value
procNetstat.TcpExt.TCPFastOpenPassive = &value
case "TCPFastOpenPassiveFail":
procNetstat.TcpExt.TCPFastOpenPassiveFail = value
procNetstat.TcpExt.TCPFastOpenPassiveFail = &value
case "TCPFastOpenListenOverflow":
procNetstat.TcpExt.TCPFastOpenListenOverflow = value
procNetstat.TcpExt.TCPFastOpenListenOverflow = &value
case "TCPFastOpenCookieReqd":
procNetstat.TcpExt.TCPFastOpenCookieReqd = value
procNetstat.TcpExt.TCPFastOpenCookieReqd = &value
case "TCPFastOpenBlackhole":
procNetstat.TcpExt.TCPFastOpenBlackhole = value
procNetstat.TcpExt.TCPFastOpenBlackhole = &value
case "TCPSpuriousRtxHostQueues":
procNetstat.TcpExt.TCPSpuriousRtxHostQueues = value
procNetstat.TcpExt.TCPSpuriousRtxHostQueues = &value
case "BusyPollRxPackets":
procNetstat.TcpExt.BusyPollRxPackets = value
procNetstat.TcpExt.BusyPollRxPackets = &value
case "TCPAutoCorking":
procNetstat.TcpExt.TCPAutoCorking = value
procNetstat.TcpExt.TCPAutoCorking = &value
case "TCPFromZeroWindowAdv":
procNetstat.TcpExt.TCPFromZeroWindowAdv = value
procNetstat.TcpExt.TCPFromZeroWindowAdv = &value
case "TCPToZeroWindowAdv":
procNetstat.TcpExt.TCPToZeroWindowAdv = value
procNetstat.TcpExt.TCPToZeroWindowAdv = &value
case "TCPWantZeroWindowAdv":
procNetstat.TcpExt.TCPWantZeroWindowAdv = value
procNetstat.TcpExt.TCPWantZeroWindowAdv = &value
case "TCPSynRetrans":
procNetstat.TcpExt.TCPSynRetrans = value
procNetstat.TcpExt.TCPSynRetrans = &value
case "TCPOrigDataSent":
procNetstat.TcpExt.TCPOrigDataSent = value
procNetstat.TcpExt.TCPOrigDataSent = &value
case "TCPHystartTrainDetect":
procNetstat.TcpExt.TCPHystartTrainDetect = value
procNetstat.TcpExt.TCPHystartTrainDetect = &value
case "TCPHystartTrainCwnd":
procNetstat.TcpExt.TCPHystartTrainCwnd = value
procNetstat.TcpExt.TCPHystartTrainCwnd = &value
case "TCPHystartDelayDetect":
procNetstat.TcpExt.TCPHystartDelayDetect = value
procNetstat.TcpExt.TCPHystartDelayDetect = &value
case "TCPHystartDelayCwnd":
procNetstat.TcpExt.TCPHystartDelayCwnd = value
procNetstat.TcpExt.TCPHystartDelayCwnd = &value
case "TCPACKSkippedSynRecv":
procNetstat.TcpExt.TCPACKSkippedSynRecv = value
procNetstat.TcpExt.TCPACKSkippedSynRecv = &value
case "TCPACKSkippedPAWS":
procNetstat.TcpExt.TCPACKSkippedPAWS = value
procNetstat.TcpExt.TCPACKSkippedPAWS = &value
case "TCPACKSkippedSeq":
procNetstat.TcpExt.TCPACKSkippedSeq = value
procNetstat.TcpExt.TCPACKSkippedSeq = &value
case "TCPACKSkippedFinWait2":
procNetstat.TcpExt.TCPACKSkippedFinWait2 = value
procNetstat.TcpExt.TCPACKSkippedFinWait2 = &value
case "TCPACKSkippedTimeWait":
procNetstat.TcpExt.TCPACKSkippedTimeWait = value
procNetstat.TcpExt.TCPACKSkippedTimeWait = &value
case "TCPACKSkippedChallenge":
procNetstat.TcpExt.TCPACKSkippedChallenge = value
procNetstat.TcpExt.TCPACKSkippedChallenge = &value
case "TCPWinProbe":
procNetstat.TcpExt.TCPWinProbe = value
procNetstat.TcpExt.TCPWinProbe = &value
case "TCPKeepAlive":
procNetstat.TcpExt.TCPKeepAlive = value
procNetstat.TcpExt.TCPKeepAlive = &value
case "TCPMTUPFail":
procNetstat.TcpExt.TCPMTUPFail = value
procNetstat.TcpExt.TCPMTUPFail = &value
case "TCPMTUPSuccess":
procNetstat.TcpExt.TCPMTUPSuccess = value
procNetstat.TcpExt.TCPMTUPSuccess = &value
case "TCPWqueueTooBig":
procNetstat.TcpExt.TCPWqueueTooBig = value
procNetstat.TcpExt.TCPWqueueTooBig = &value
}
case "IpExt":
switch key {
case "InNoRoutes":
procNetstat.IpExt.InNoRoutes = value
procNetstat.IpExt.InNoRoutes = &value
case "InTruncatedPkts":
procNetstat.IpExt.InTruncatedPkts = value
procNetstat.IpExt.InTruncatedPkts = &value
case "InMcastPkts":
procNetstat.IpExt.InMcastPkts = value
procNetstat.IpExt.InMcastPkts = &value
case "OutMcastPkts":
procNetstat.IpExt.OutMcastPkts = value
procNetstat.IpExt.OutMcastPkts = &value
case "InBcastPkts":
procNetstat.IpExt.InBcastPkts = value
procNetstat.IpExt.InBcastPkts = &value
case "OutBcastPkts":
procNetstat.IpExt.OutBcastPkts = value
procNetstat.IpExt.OutBcastPkts = &value
case "InOctets":
procNetstat.IpExt.InOctets = value
procNetstat.IpExt.InOctets = &value
case "OutOctets":
procNetstat.IpExt.OutOctets = value
procNetstat.IpExt.OutOctets = &value
case "InMcastOctets":
procNetstat.IpExt.InMcastOctets = value
procNetstat.IpExt.InMcastOctets = &value
case "OutMcastOctets":
procNetstat.IpExt.OutMcastOctets = value
procNetstat.IpExt.OutMcastOctets = &value
case "InBcastOctets":
procNetstat.IpExt.InBcastOctets = value
procNetstat.IpExt.InBcastOctets = &value
case "OutBcastOctets":
procNetstat.IpExt.OutBcastOctets = value
procNetstat.IpExt.OutBcastOctets = &value
case "InCsumErrors":
procNetstat.IpExt.InCsumErrors = value
procNetstat.IpExt.InCsumErrors = &value
case "InNoECTPkts":
procNetstat.IpExt.InNoECTPkts = value
procNetstat.IpExt.InNoECTPkts = &value
case "InECT1Pkts":
procNetstat.IpExt.InECT1Pkts = value
procNetstat.IpExt.InECT1Pkts = &value
case "InECT0Pkts":
procNetstat.IpExt.InECT0Pkts = value
procNetstat.IpExt.InECT0Pkts = &value
case "InCEPkts":
procNetstat.IpExt.InCEPkts = value
procNetstat.IpExt.InCEPkts = &value
case "ReasmOverlaps":
procNetstat.IpExt.ReasmOverlaps = value
procNetstat.IpExt.ReasmOverlaps = &value
}
}
}

View File

@ -37,100 +37,100 @@ type ProcSnmp struct {
}
type Ip struct { // nolint:revive
Forwarding float64
DefaultTTL float64
InReceives float64
InHdrErrors float64
InAddrErrors float64
ForwDatagrams float64
InUnknownProtos float64
InDiscards float64
InDelivers float64
OutRequests float64
OutDiscards float64
OutNoRoutes float64
ReasmTimeout float64
ReasmReqds float64
ReasmOKs float64
ReasmFails float64
FragOKs float64
FragFails float64
FragCreates float64
Forwarding *float64
DefaultTTL *float64
InReceives *float64
InHdrErrors *float64
InAddrErrors *float64
ForwDatagrams *float64
InUnknownProtos *float64
InDiscards *float64
InDelivers *float64
OutRequests *float64
OutDiscards *float64
OutNoRoutes *float64
ReasmTimeout *float64
ReasmReqds *float64
ReasmOKs *float64
ReasmFails *float64
FragOKs *float64
FragFails *float64
FragCreates *float64
}
type Icmp struct {
InMsgs float64
InErrors float64
InCsumErrors float64
InDestUnreachs float64
InTimeExcds float64
InParmProbs float64
InSrcQuenchs float64
InRedirects float64
InEchos float64
InEchoReps float64
InTimestamps float64
InTimestampReps float64
InAddrMasks float64
InAddrMaskReps float64
OutMsgs float64
OutErrors float64
OutDestUnreachs float64
OutTimeExcds float64
OutParmProbs float64
OutSrcQuenchs float64
OutRedirects float64
OutEchos float64
OutEchoReps float64
OutTimestamps float64
OutTimestampReps float64
OutAddrMasks float64
OutAddrMaskReps float64
type Icmp struct { // nolint:revive
InMsgs *float64
InErrors *float64
InCsumErrors *float64
InDestUnreachs *float64
InTimeExcds *float64
InParmProbs *float64
InSrcQuenchs *float64
InRedirects *float64
InEchos *float64
InEchoReps *float64
InTimestamps *float64
InTimestampReps *float64
InAddrMasks *float64
InAddrMaskReps *float64
OutMsgs *float64
OutErrors *float64
OutDestUnreachs *float64
OutTimeExcds *float64
OutParmProbs *float64
OutSrcQuenchs *float64
OutRedirects *float64
OutEchos *float64
OutEchoReps *float64
OutTimestamps *float64
OutTimestampReps *float64
OutAddrMasks *float64
OutAddrMaskReps *float64
}
type IcmpMsg struct {
InType3 float64
OutType3 float64
InType3 *float64
OutType3 *float64
}
type Tcp struct { // nolint:revive
RtoAlgorithm float64
RtoMin float64
RtoMax float64
MaxConn float64
ActiveOpens float64
PassiveOpens float64
AttemptFails float64
EstabResets float64
CurrEstab float64
InSegs float64
OutSegs float64
RetransSegs float64
InErrs float64
OutRsts float64
InCsumErrors float64
RtoAlgorithm *float64
RtoMin *float64
RtoMax *float64
MaxConn *float64
ActiveOpens *float64
PassiveOpens *float64
AttemptFails *float64
EstabResets *float64
CurrEstab *float64
InSegs *float64
OutSegs *float64
RetransSegs *float64
InErrs *float64
OutRsts *float64
InCsumErrors *float64
}
type Udp struct { // nolint:revive
InDatagrams float64
NoPorts float64
InErrors float64
OutDatagrams float64
RcvbufErrors float64
SndbufErrors float64
InCsumErrors float64
IgnoredMulti float64
InDatagrams *float64
NoPorts *float64
InErrors *float64
OutDatagrams *float64
RcvbufErrors *float64
SndbufErrors *float64
InCsumErrors *float64
IgnoredMulti *float64
}
type UdpLite struct { // nolint:revive
InDatagrams float64
NoPorts float64
InErrors float64
OutDatagrams float64
RcvbufErrors float64
SndbufErrors float64
InCsumErrors float64
IgnoredMulti float64
InDatagrams *float64
NoPorts *float64
InErrors *float64
OutDatagrams *float64
RcvbufErrors *float64
SndbufErrors *float64
InCsumErrors *float64
IgnoredMulti *float64
}
func (p Proc) Snmp() (ProcSnmp, error) {
@ -173,178 +173,178 @@ func parseSnmp(r io.Reader, fileName string) (ProcSnmp, error) {
case "Ip":
switch key {
case "Forwarding":
procSnmp.Ip.Forwarding = value
procSnmp.Ip.Forwarding = &value
case "DefaultTTL":
procSnmp.Ip.DefaultTTL = value
procSnmp.Ip.DefaultTTL = &value
case "InReceives":
procSnmp.Ip.InReceives = value
procSnmp.Ip.InReceives = &value
case "InHdrErrors":
procSnmp.Ip.InHdrErrors = value
procSnmp.Ip.InHdrErrors = &value
case "InAddrErrors":
procSnmp.Ip.InAddrErrors = value
procSnmp.Ip.InAddrErrors = &value
case "ForwDatagrams":
procSnmp.Ip.ForwDatagrams = value
procSnmp.Ip.ForwDatagrams = &value
case "InUnknownProtos":
procSnmp.Ip.InUnknownProtos = value
procSnmp.Ip.InUnknownProtos = &value
case "InDiscards":
procSnmp.Ip.InDiscards = value
procSnmp.Ip.InDiscards = &value
case "InDelivers":
procSnmp.Ip.InDelivers = value
procSnmp.Ip.InDelivers = &value
case "OutRequests":
procSnmp.Ip.OutRequests = value
procSnmp.Ip.OutRequests = &value
case "OutDiscards":
procSnmp.Ip.OutDiscards = value
procSnmp.Ip.OutDiscards = &value
case "OutNoRoutes":
procSnmp.Ip.OutNoRoutes = value
procSnmp.Ip.OutNoRoutes = &value
case "ReasmTimeout":
procSnmp.Ip.ReasmTimeout = value
procSnmp.Ip.ReasmTimeout = &value
case "ReasmReqds":
procSnmp.Ip.ReasmReqds = value
procSnmp.Ip.ReasmReqds = &value
case "ReasmOKs":
procSnmp.Ip.ReasmOKs = value
procSnmp.Ip.ReasmOKs = &value
case "ReasmFails":
procSnmp.Ip.ReasmFails = value
procSnmp.Ip.ReasmFails = &value
case "FragOKs":
procSnmp.Ip.FragOKs = value
procSnmp.Ip.FragOKs = &value
case "FragFails":
procSnmp.Ip.FragFails = value
procSnmp.Ip.FragFails = &value
case "FragCreates":
procSnmp.Ip.FragCreates = value
procSnmp.Ip.FragCreates = &value
}
case "Icmp":
switch key {
case "InMsgs":
procSnmp.Icmp.InMsgs = value
procSnmp.Icmp.InMsgs = &value
case "InErrors":
procSnmp.Icmp.InErrors = value
procSnmp.Icmp.InErrors = &value
case "InCsumErrors":
procSnmp.Icmp.InCsumErrors = value
procSnmp.Icmp.InCsumErrors = &value
case "InDestUnreachs":
procSnmp.Icmp.InDestUnreachs = value
procSnmp.Icmp.InDestUnreachs = &value
case "InTimeExcds":
procSnmp.Icmp.InTimeExcds = value
procSnmp.Icmp.InTimeExcds = &value
case "InParmProbs":
procSnmp.Icmp.InParmProbs = value
procSnmp.Icmp.InParmProbs = &value
case "InSrcQuenchs":
procSnmp.Icmp.InSrcQuenchs = value
procSnmp.Icmp.InSrcQuenchs = &value
case "InRedirects":
procSnmp.Icmp.InRedirects = value
procSnmp.Icmp.InRedirects = &value
case "InEchos":
procSnmp.Icmp.InEchos = value
procSnmp.Icmp.InEchos = &value
case "InEchoReps":
procSnmp.Icmp.InEchoReps = value
procSnmp.Icmp.InEchoReps = &value
case "InTimestamps":
procSnmp.Icmp.InTimestamps = value
procSnmp.Icmp.InTimestamps = &value
case "InTimestampReps":
procSnmp.Icmp.InTimestampReps = value
procSnmp.Icmp.InTimestampReps = &value
case "InAddrMasks":
procSnmp.Icmp.InAddrMasks = value
procSnmp.Icmp.InAddrMasks = &value
case "InAddrMaskReps":
procSnmp.Icmp.InAddrMaskReps = value
procSnmp.Icmp.InAddrMaskReps = &value
case "OutMsgs":
procSnmp.Icmp.OutMsgs = value
procSnmp.Icmp.OutMsgs = &value
case "OutErrors":
procSnmp.Icmp.OutErrors = value
procSnmp.Icmp.OutErrors = &value
case "OutDestUnreachs":
procSnmp.Icmp.OutDestUnreachs = value
procSnmp.Icmp.OutDestUnreachs = &value
case "OutTimeExcds":
procSnmp.Icmp.OutTimeExcds = value
procSnmp.Icmp.OutTimeExcds = &value
case "OutParmProbs":
procSnmp.Icmp.OutParmProbs = value
procSnmp.Icmp.OutParmProbs = &value
case "OutSrcQuenchs":
procSnmp.Icmp.OutSrcQuenchs = value
procSnmp.Icmp.OutSrcQuenchs = &value
case "OutRedirects":
procSnmp.Icmp.OutRedirects = value
procSnmp.Icmp.OutRedirects = &value
case "OutEchos":
procSnmp.Icmp.OutEchos = value
procSnmp.Icmp.OutEchos = &value
case "OutEchoReps":
procSnmp.Icmp.OutEchoReps = value
procSnmp.Icmp.OutEchoReps = &value
case "OutTimestamps":
procSnmp.Icmp.OutTimestamps = value
procSnmp.Icmp.OutTimestamps = &value
case "OutTimestampReps":
procSnmp.Icmp.OutTimestampReps = value
procSnmp.Icmp.OutTimestampReps = &value
case "OutAddrMasks":
procSnmp.Icmp.OutAddrMasks = value
procSnmp.Icmp.OutAddrMasks = &value
case "OutAddrMaskReps":
procSnmp.Icmp.OutAddrMaskReps = value
procSnmp.Icmp.OutAddrMaskReps = &value
}
case "IcmpMsg":
switch key {
case "InType3":
procSnmp.IcmpMsg.InType3 = value
procSnmp.IcmpMsg.InType3 = &value
case "OutType3":
procSnmp.IcmpMsg.OutType3 = value
procSnmp.IcmpMsg.OutType3 = &value
}
case "Tcp":
switch key {
case "RtoAlgorithm":
procSnmp.Tcp.RtoAlgorithm = value
procSnmp.Tcp.RtoAlgorithm = &value
case "RtoMin":
procSnmp.Tcp.RtoMin = value
procSnmp.Tcp.RtoMin = &value
case "RtoMax":
procSnmp.Tcp.RtoMax = value
procSnmp.Tcp.RtoMax = &value
case "MaxConn":
procSnmp.Tcp.MaxConn = value
procSnmp.Tcp.MaxConn = &value
case "ActiveOpens":
procSnmp.Tcp.ActiveOpens = value
procSnmp.Tcp.ActiveOpens = &value
case "PassiveOpens":
procSnmp.Tcp.PassiveOpens = value
procSnmp.Tcp.PassiveOpens = &value
case "AttemptFails":
procSnmp.Tcp.AttemptFails = value
procSnmp.Tcp.AttemptFails = &value
case "EstabResets":
procSnmp.Tcp.EstabResets = value
procSnmp.Tcp.EstabResets = &value
case "CurrEstab":
procSnmp.Tcp.CurrEstab = value
procSnmp.Tcp.CurrEstab = &value
case "InSegs":
procSnmp.Tcp.InSegs = value
procSnmp.Tcp.InSegs = &value
case "OutSegs":
procSnmp.Tcp.OutSegs = value
procSnmp.Tcp.OutSegs = &value
case "RetransSegs":
procSnmp.Tcp.RetransSegs = value
procSnmp.Tcp.RetransSegs = &value
case "InErrs":
procSnmp.Tcp.InErrs = value
procSnmp.Tcp.InErrs = &value
case "OutRsts":
procSnmp.Tcp.OutRsts = value
procSnmp.Tcp.OutRsts = &value
case "InCsumErrors":
procSnmp.Tcp.InCsumErrors = value
procSnmp.Tcp.InCsumErrors = &value
}
case "Udp":
switch key {
case "InDatagrams":
procSnmp.Udp.InDatagrams = value
procSnmp.Udp.InDatagrams = &value
case "NoPorts":
procSnmp.Udp.NoPorts = value
procSnmp.Udp.NoPorts = &value
case "InErrors":
procSnmp.Udp.InErrors = value
procSnmp.Udp.InErrors = &value
case "OutDatagrams":
procSnmp.Udp.OutDatagrams = value
procSnmp.Udp.OutDatagrams = &value
case "RcvbufErrors":
procSnmp.Udp.RcvbufErrors = value
procSnmp.Udp.RcvbufErrors = &value
case "SndbufErrors":
procSnmp.Udp.SndbufErrors = value
procSnmp.Udp.SndbufErrors = &value
case "InCsumErrors":
procSnmp.Udp.InCsumErrors = value
procSnmp.Udp.InCsumErrors = &value
case "IgnoredMulti":
procSnmp.Udp.IgnoredMulti = value
procSnmp.Udp.IgnoredMulti = &value
}
case "UdpLite":
switch key {
case "InDatagrams":
procSnmp.UdpLite.InDatagrams = value
procSnmp.UdpLite.InDatagrams = &value
case "NoPorts":
procSnmp.UdpLite.NoPorts = value
procSnmp.UdpLite.NoPorts = &value
case "InErrors":
procSnmp.UdpLite.InErrors = value
procSnmp.UdpLite.InErrors = &value
case "OutDatagrams":
procSnmp.UdpLite.OutDatagrams = value
procSnmp.UdpLite.OutDatagrams = &value
case "RcvbufErrors":
procSnmp.UdpLite.RcvbufErrors = value
procSnmp.UdpLite.RcvbufErrors = &value
case "SndbufErrors":
procSnmp.UdpLite.SndbufErrors = value
procSnmp.UdpLite.SndbufErrors = &value
case "InCsumErrors":
procSnmp.UdpLite.InCsumErrors = value
procSnmp.UdpLite.InCsumErrors = &value
case "IgnoredMulti":
procSnmp.UdpLite.IgnoredMulti = value
procSnmp.UdpLite.IgnoredMulti = &value
}
}
}

View File

@ -36,106 +36,106 @@ type ProcSnmp6 struct {
}
type Ip6 struct { // nolint:revive
InReceives float64
InHdrErrors float64
InTooBigErrors float64
InNoRoutes float64
InAddrErrors float64
InUnknownProtos float64
InTruncatedPkts float64
InDiscards float64
InDelivers float64
OutForwDatagrams float64
OutRequests float64
OutDiscards float64
OutNoRoutes float64
ReasmTimeout float64
ReasmReqds float64
ReasmOKs float64
ReasmFails float64
FragOKs float64
FragFails float64
FragCreates float64
InMcastPkts float64
OutMcastPkts float64
InOctets float64
OutOctets float64
InMcastOctets float64
OutMcastOctets float64
InBcastOctets float64
OutBcastOctets float64
InNoECTPkts float64
InECT1Pkts float64
InECT0Pkts float64
InCEPkts float64
InReceives *float64
InHdrErrors *float64
InTooBigErrors *float64
InNoRoutes *float64
InAddrErrors *float64
InUnknownProtos *float64
InTruncatedPkts *float64
InDiscards *float64
InDelivers *float64
OutForwDatagrams *float64
OutRequests *float64
OutDiscards *float64
OutNoRoutes *float64
ReasmTimeout *float64
ReasmReqds *float64
ReasmOKs *float64
ReasmFails *float64
FragOKs *float64
FragFails *float64
FragCreates *float64
InMcastPkts *float64
OutMcastPkts *float64
InOctets *float64
OutOctets *float64
InMcastOctets *float64
OutMcastOctets *float64
InBcastOctets *float64
OutBcastOctets *float64
InNoECTPkts *float64
InECT1Pkts *float64
InECT0Pkts *float64
InCEPkts *float64
}
type Icmp6 struct {
InMsgs float64
InErrors float64
OutMsgs float64
OutErrors float64
InCsumErrors float64
InDestUnreachs float64
InPktTooBigs float64
InTimeExcds float64
InParmProblems float64
InEchos float64
InEchoReplies float64
InGroupMembQueries float64
InGroupMembResponses float64
InGroupMembReductions float64
InRouterSolicits float64
InRouterAdvertisements float64
InNeighborSolicits float64
InNeighborAdvertisements float64
InRedirects float64
InMLDv2Reports float64
OutDestUnreachs float64
OutPktTooBigs float64
OutTimeExcds float64
OutParmProblems float64
OutEchos float64
OutEchoReplies float64
OutGroupMembQueries float64
OutGroupMembResponses float64
OutGroupMembReductions float64
OutRouterSolicits float64
OutRouterAdvertisements float64
OutNeighborSolicits float64
OutNeighborAdvertisements float64
OutRedirects float64
OutMLDv2Reports float64
InType1 float64
InType134 float64
InType135 float64
InType136 float64
InType143 float64
OutType133 float64
OutType135 float64
OutType136 float64
OutType143 float64
InMsgs *float64
InErrors *float64
OutMsgs *float64
OutErrors *float64
InCsumErrors *float64
InDestUnreachs *float64
InPktTooBigs *float64
InTimeExcds *float64
InParmProblems *float64
InEchos *float64
InEchoReplies *float64
InGroupMembQueries *float64
InGroupMembResponses *float64
InGroupMembReductions *float64
InRouterSolicits *float64
InRouterAdvertisements *float64
InNeighborSolicits *float64
InNeighborAdvertisements *float64
InRedirects *float64
InMLDv2Reports *float64
OutDestUnreachs *float64
OutPktTooBigs *float64
OutTimeExcds *float64
OutParmProblems *float64
OutEchos *float64
OutEchoReplies *float64
OutGroupMembQueries *float64
OutGroupMembResponses *float64
OutGroupMembReductions *float64
OutRouterSolicits *float64
OutRouterAdvertisements *float64
OutNeighborSolicits *float64
OutNeighborAdvertisements *float64
OutRedirects *float64
OutMLDv2Reports *float64
InType1 *float64
InType134 *float64
InType135 *float64
InType136 *float64
InType143 *float64
OutType133 *float64
OutType135 *float64
OutType136 *float64
OutType143 *float64
}
type Udp6 struct { // nolint:revive
InDatagrams float64
NoPorts float64
InErrors float64
OutDatagrams float64
RcvbufErrors float64
SndbufErrors float64
InCsumErrors float64
IgnoredMulti float64
InDatagrams *float64
NoPorts *float64
InErrors *float64
OutDatagrams *float64
RcvbufErrors *float64
SndbufErrors *float64
InCsumErrors *float64
IgnoredMulti *float64
}
type UdpLite6 struct { // nolint:revive
InDatagrams float64
NoPorts float64
InErrors float64
OutDatagrams float64
RcvbufErrors float64
SndbufErrors float64
InCsumErrors float64
InDatagrams *float64
NoPorts *float64
InErrors *float64
OutDatagrams *float64
RcvbufErrors *float64
SndbufErrors *float64
InCsumErrors *float64
}
func (p Proc) Snmp6() (ProcSnmp6, error) {
@ -182,197 +182,197 @@ func parseSNMP6Stats(r io.Reader) (ProcSnmp6, error) {
case "Ip6":
switch key {
case "InReceives":
procSnmp6.Ip6.InReceives = value
procSnmp6.Ip6.InReceives = &value
case "InHdrErrors":
procSnmp6.Ip6.InHdrErrors = value
procSnmp6.Ip6.InHdrErrors = &value
case "InTooBigErrors":
procSnmp6.Ip6.InTooBigErrors = value
procSnmp6.Ip6.InTooBigErrors = &value
case "InNoRoutes":
procSnmp6.Ip6.InNoRoutes = value
procSnmp6.Ip6.InNoRoutes = &value
case "InAddrErrors":
procSnmp6.Ip6.InAddrErrors = value
procSnmp6.Ip6.InAddrErrors = &value
case "InUnknownProtos":
procSnmp6.Ip6.InUnknownProtos = value
procSnmp6.Ip6.InUnknownProtos = &value
case "InTruncatedPkts":
procSnmp6.Ip6.InTruncatedPkts = value
procSnmp6.Ip6.InTruncatedPkts = &value
case "InDiscards":
procSnmp6.Ip6.InDiscards = value
procSnmp6.Ip6.InDiscards = &value
case "InDelivers":
procSnmp6.Ip6.InDelivers = value
procSnmp6.Ip6.InDelivers = &value
case "OutForwDatagrams":
procSnmp6.Ip6.OutForwDatagrams = value
procSnmp6.Ip6.OutForwDatagrams = &value
case "OutRequests":
procSnmp6.Ip6.OutRequests = value
procSnmp6.Ip6.OutRequests = &value
case "OutDiscards":
procSnmp6.Ip6.OutDiscards = value
procSnmp6.Ip6.OutDiscards = &value
case "OutNoRoutes":
procSnmp6.Ip6.OutNoRoutes = value
procSnmp6.Ip6.OutNoRoutes = &value
case "ReasmTimeout":
procSnmp6.Ip6.ReasmTimeout = value
procSnmp6.Ip6.ReasmTimeout = &value
case "ReasmReqds":
procSnmp6.Ip6.ReasmReqds = value
procSnmp6.Ip6.ReasmReqds = &value
case "ReasmOKs":
procSnmp6.Ip6.ReasmOKs = value
procSnmp6.Ip6.ReasmOKs = &value
case "ReasmFails":
procSnmp6.Ip6.ReasmFails = value
procSnmp6.Ip6.ReasmFails = &value
case "FragOKs":
procSnmp6.Ip6.FragOKs = value
procSnmp6.Ip6.FragOKs = &value
case "FragFails":
procSnmp6.Ip6.FragFails = value
procSnmp6.Ip6.FragFails = &value
case "FragCreates":
procSnmp6.Ip6.FragCreates = value
procSnmp6.Ip6.FragCreates = &value
case "InMcastPkts":
procSnmp6.Ip6.InMcastPkts = value
procSnmp6.Ip6.InMcastPkts = &value
case "OutMcastPkts":
procSnmp6.Ip6.OutMcastPkts = value
procSnmp6.Ip6.OutMcastPkts = &value
case "InOctets":
procSnmp6.Ip6.InOctets = value
procSnmp6.Ip6.InOctets = &value
case "OutOctets":
procSnmp6.Ip6.OutOctets = value
procSnmp6.Ip6.OutOctets = &value
case "InMcastOctets":
procSnmp6.Ip6.InMcastOctets = value
procSnmp6.Ip6.InMcastOctets = &value
case "OutMcastOctets":
procSnmp6.Ip6.OutMcastOctets = value
procSnmp6.Ip6.OutMcastOctets = &value
case "InBcastOctets":
procSnmp6.Ip6.InBcastOctets = value
procSnmp6.Ip6.InBcastOctets = &value
case "OutBcastOctets":
procSnmp6.Ip6.OutBcastOctets = value
procSnmp6.Ip6.OutBcastOctets = &value
case "InNoECTPkts":
procSnmp6.Ip6.InNoECTPkts = value
procSnmp6.Ip6.InNoECTPkts = &value
case "InECT1Pkts":
procSnmp6.Ip6.InECT1Pkts = value
procSnmp6.Ip6.InECT1Pkts = &value
case "InECT0Pkts":
procSnmp6.Ip6.InECT0Pkts = value
procSnmp6.Ip6.InECT0Pkts = &value
case "InCEPkts":
procSnmp6.Ip6.InCEPkts = value
procSnmp6.Ip6.InCEPkts = &value
}
case "Icmp6":
switch key {
case "InMsgs":
procSnmp6.Icmp6.InMsgs = value
procSnmp6.Icmp6.InMsgs = &value
case "InErrors":
procSnmp6.Icmp6.InErrors = value
procSnmp6.Icmp6.InErrors = &value
case "OutMsgs":
procSnmp6.Icmp6.OutMsgs = value
procSnmp6.Icmp6.OutMsgs = &value
case "OutErrors":
procSnmp6.Icmp6.OutErrors = value
procSnmp6.Icmp6.OutErrors = &value
case "InCsumErrors":
procSnmp6.Icmp6.InCsumErrors = value
procSnmp6.Icmp6.InCsumErrors = &value
case "InDestUnreachs":
procSnmp6.Icmp6.InDestUnreachs = value
procSnmp6.Icmp6.InDestUnreachs = &value
case "InPktTooBigs":
procSnmp6.Icmp6.InPktTooBigs = value
procSnmp6.Icmp6.InPktTooBigs = &value
case "InTimeExcds":
procSnmp6.Icmp6.InTimeExcds = value
procSnmp6.Icmp6.InTimeExcds = &value
case "InParmProblems":
procSnmp6.Icmp6.InParmProblems = value
procSnmp6.Icmp6.InParmProblems = &value
case "InEchos":
procSnmp6.Icmp6.InEchos = value
procSnmp6.Icmp6.InEchos = &value
case "InEchoReplies":
procSnmp6.Icmp6.InEchoReplies = value
procSnmp6.Icmp6.InEchoReplies = &value
case "InGroupMembQueries":
procSnmp6.Icmp6.InGroupMembQueries = value
procSnmp6.Icmp6.InGroupMembQueries = &value
case "InGroupMembResponses":
procSnmp6.Icmp6.InGroupMembResponses = value
procSnmp6.Icmp6.InGroupMembResponses = &value
case "InGroupMembReductions":
procSnmp6.Icmp6.InGroupMembReductions = value
procSnmp6.Icmp6.InGroupMembReductions = &value
case "InRouterSolicits":
procSnmp6.Icmp6.InRouterSolicits = value
procSnmp6.Icmp6.InRouterSolicits = &value
case "InRouterAdvertisements":
procSnmp6.Icmp6.InRouterAdvertisements = value
procSnmp6.Icmp6.InRouterAdvertisements = &value
case "InNeighborSolicits":
procSnmp6.Icmp6.InNeighborSolicits = value
procSnmp6.Icmp6.InNeighborSolicits = &value
case "InNeighborAdvertisements":
procSnmp6.Icmp6.InNeighborAdvertisements = value
procSnmp6.Icmp6.InNeighborAdvertisements = &value
case "InRedirects":
procSnmp6.Icmp6.InRedirects = value
procSnmp6.Icmp6.InRedirects = &value
case "InMLDv2Reports":
procSnmp6.Icmp6.InMLDv2Reports = value
procSnmp6.Icmp6.InMLDv2Reports = &value
case "OutDestUnreachs":
procSnmp6.Icmp6.OutDestUnreachs = value
procSnmp6.Icmp6.OutDestUnreachs = &value
case "OutPktTooBigs":
procSnmp6.Icmp6.OutPktTooBigs = value
procSnmp6.Icmp6.OutPktTooBigs = &value
case "OutTimeExcds":
procSnmp6.Icmp6.OutTimeExcds = value
procSnmp6.Icmp6.OutTimeExcds = &value
case "OutParmProblems":
procSnmp6.Icmp6.OutParmProblems = value
procSnmp6.Icmp6.OutParmProblems = &value
case "OutEchos":
procSnmp6.Icmp6.OutEchos = value
procSnmp6.Icmp6.OutEchos = &value
case "OutEchoReplies":
procSnmp6.Icmp6.OutEchoReplies = value
procSnmp6.Icmp6.OutEchoReplies = &value
case "OutGroupMembQueries":
procSnmp6.Icmp6.OutGroupMembQueries = value
procSnmp6.Icmp6.OutGroupMembQueries = &value
case "OutGroupMembResponses":
procSnmp6.Icmp6.OutGroupMembResponses = value
procSnmp6.Icmp6.OutGroupMembResponses = &value
case "OutGroupMembReductions":
procSnmp6.Icmp6.OutGroupMembReductions = value
procSnmp6.Icmp6.OutGroupMembReductions = &value
case "OutRouterSolicits":
procSnmp6.Icmp6.OutRouterSolicits = value
procSnmp6.Icmp6.OutRouterSolicits = &value
case "OutRouterAdvertisements":
procSnmp6.Icmp6.OutRouterAdvertisements = value
procSnmp6.Icmp6.OutRouterAdvertisements = &value
case "OutNeighborSolicits":
procSnmp6.Icmp6.OutNeighborSolicits = value
procSnmp6.Icmp6.OutNeighborSolicits = &value
case "OutNeighborAdvertisements":
procSnmp6.Icmp6.OutNeighborAdvertisements = value
procSnmp6.Icmp6.OutNeighborAdvertisements = &value
case "OutRedirects":
procSnmp6.Icmp6.OutRedirects = value
procSnmp6.Icmp6.OutRedirects = &value
case "OutMLDv2Reports":
procSnmp6.Icmp6.OutMLDv2Reports = value
procSnmp6.Icmp6.OutMLDv2Reports = &value
case "InType1":
procSnmp6.Icmp6.InType1 = value
procSnmp6.Icmp6.InType1 = &value
case "InType134":
procSnmp6.Icmp6.InType134 = value
procSnmp6.Icmp6.InType134 = &value
case "InType135":
procSnmp6.Icmp6.InType135 = value
procSnmp6.Icmp6.InType135 = &value
case "InType136":
procSnmp6.Icmp6.InType136 = value
procSnmp6.Icmp6.InType136 = &value
case "InType143":
procSnmp6.Icmp6.InType143 = value
procSnmp6.Icmp6.InType143 = &value
case "OutType133":
procSnmp6.Icmp6.OutType133 = value
procSnmp6.Icmp6.OutType133 = &value
case "OutType135":
procSnmp6.Icmp6.OutType135 = value
procSnmp6.Icmp6.OutType135 = &value
case "OutType136":
procSnmp6.Icmp6.OutType136 = value
procSnmp6.Icmp6.OutType136 = &value
case "OutType143":
procSnmp6.Icmp6.OutType143 = value
procSnmp6.Icmp6.OutType143 = &value
}
case "Udp6":
switch key {
case "InDatagrams":
procSnmp6.Udp6.InDatagrams = value
procSnmp6.Udp6.InDatagrams = &value
case "NoPorts":
procSnmp6.Udp6.NoPorts = value
procSnmp6.Udp6.NoPorts = &value
case "InErrors":
procSnmp6.Udp6.InErrors = value
procSnmp6.Udp6.InErrors = &value
case "OutDatagrams":
procSnmp6.Udp6.OutDatagrams = value
procSnmp6.Udp6.OutDatagrams = &value
case "RcvbufErrors":
procSnmp6.Udp6.RcvbufErrors = value
procSnmp6.Udp6.RcvbufErrors = &value
case "SndbufErrors":
procSnmp6.Udp6.SndbufErrors = value
procSnmp6.Udp6.SndbufErrors = &value
case "InCsumErrors":
procSnmp6.Udp6.InCsumErrors = value
procSnmp6.Udp6.InCsumErrors = &value
case "IgnoredMulti":
procSnmp6.Udp6.IgnoredMulti = value
procSnmp6.Udp6.IgnoredMulti = &value
}
case "UdpLite6":
switch key {
case "InDatagrams":
procSnmp6.UdpLite6.InDatagrams = value
procSnmp6.UdpLite6.InDatagrams = &value
case "NoPorts":
procSnmp6.UdpLite6.NoPorts = value
procSnmp6.UdpLite6.NoPorts = &value
case "InErrors":
procSnmp6.UdpLite6.InErrors = value
procSnmp6.UdpLite6.InErrors = &value
case "OutDatagrams":
procSnmp6.UdpLite6.OutDatagrams = value
procSnmp6.UdpLite6.OutDatagrams = &value
case "RcvbufErrors":
procSnmp6.UdpLite6.RcvbufErrors = value
procSnmp6.UdpLite6.RcvbufErrors = &value
case "SndbufErrors":
procSnmp6.UdpLite6.SndbufErrors = value
procSnmp6.UdpLite6.SndbufErrors = &value
case "InCsumErrors":
procSnmp6.UdpLite6.InCsumErrors = value
procSnmp6.UdpLite6.InCsumErrors = &value
}
}
}

View File

@ -18,7 +18,6 @@ import (
"fmt"
"os"
"github.com/prometheus/procfs/internal/fs"
"github.com/prometheus/procfs/internal/util"
)
@ -102,6 +101,8 @@ type ProcStat struct {
RSS int
// Soft limit in bytes on the rss of the process.
RSSLimit uint64
// CPU number last executed on.
Processor uint
// Real-time scheduling priority, a number in the range 1 to 99 for processes
// scheduled under a real-time policy, or 0, for non-real-time processes.
RTPriority uint
@ -110,7 +111,7 @@ type ProcStat struct {
// Aggregated block I/O delays, measured in clock ticks (centiseconds).
DelayAcctBlkIOTicks uint64
proc fs.FS
proc FS
}
// NewStat returns the current status information of the process.
@ -184,7 +185,7 @@ func (p Proc) Stat() (ProcStat, error) {
&ignoreUint64,
&ignoreUint64,
&ignoreInt64,
&ignoreInt64,
&s.Processor,
&s.RTPriority,
&s.Policy,
&s.DelayAcctBlkIOTicks,
@ -208,8 +209,7 @@ func (s ProcStat) ResidentMemory() int {
// StartTime returns the unix timestamp of the process in seconds.
func (s ProcStat) StartTime() (float64, error) {
fs := FS{proc: s.proc}
stat, err := fs.Stat()
stat, err := s.proc.Stat()
if err != nil {
return 0, err
}

View File

@ -15,6 +15,7 @@ package procfs
import (
"bytes"
"sort"
"strconv"
"strings"
@ -76,6 +77,9 @@ type ProcStatus struct {
UIDs [4]string
// GIDs of the process (Real, effective, saved set, and filesystem GIDs)
GIDs [4]string
// CpusAllowedList: List of cpu cores processes are allowed to run on.
CpusAllowedList []uint64
}
// NewStatus returns the current status information of the process.
@ -96,10 +100,10 @@ func (p Proc) NewStatus() (ProcStatus, error) {
kv := strings.SplitN(line, ":", 2)
// removes spaces
k := string(strings.TrimSpace(kv[0]))
v := string(strings.TrimSpace(kv[1]))
k := strings.TrimSpace(kv[0])
v := strings.TrimSpace(kv[1])
// removes "kB"
v = string(bytes.Trim([]byte(v), " kB"))
v = strings.TrimSuffix(v, " kB")
// value to int when possible
// we can skip error check here, 'cause vKBytes is not used when value is a string
@ -161,10 +165,38 @@ func (s *ProcStatus) fillStatus(k string, vString string, vUint uint64, vUintByt
s.VoluntaryCtxtSwitches = vUint
case "nonvoluntary_ctxt_switches":
s.NonVoluntaryCtxtSwitches = vUint
case "Cpus_allowed_list":
s.CpusAllowedList = calcCpusAllowedList(vString)
}
}
// TotalCtxtSwitches returns the total context switch.
func (s ProcStatus) TotalCtxtSwitches() uint64 {
return s.VoluntaryCtxtSwitches + s.NonVoluntaryCtxtSwitches
}
func calcCpusAllowedList(cpuString string) []uint64 {
s := strings.Split(cpuString, ",")
var g []uint64
for _, cpu := range s {
// parse cpu ranges, example: 1-3=[1,2,3]
if l := strings.Split(strings.TrimSpace(cpu), "-"); len(l) > 1 {
startCPU, _ := strconv.ParseUint(l[0], 10, 64)
endCPU, _ := strconv.ParseUint(l[1], 10, 64)
for i := startCPU; i <= endCPU; i++ {
g = append(g, i)
}
} else if len(l) == 1 {
cpu, _ := strconv.ParseUint(l[0], 10, 64)
g = append(g, cpu)
}
}
sort.Slice(g, func(i, j int) bool { return g[i] < g[j] })
return g
}

Some files were not shown because too many files have changed in this diff Show More