Merge pull request #4904 from RainbowMango/pr_bump_metrics-server071
Bump metrics-server to v0.7.1
This commit is contained in:
commit
b93d71ec5a
19
go.mod
19
go.mod
|
@ -14,8 +14,8 @@ require (
|
||||||
github.com/kr/pretty v0.3.1
|
github.com/kr/pretty v0.3.1
|
||||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f
|
||||||
github.com/olekukonko/tablewriter v0.0.5
|
github.com/olekukonko/tablewriter v0.0.5
|
||||||
github.com/onsi/ginkgo/v2 v2.13.0
|
github.com/onsi/ginkgo/v2 v2.14.0
|
||||||
github.com/onsi/gomega v1.29.0
|
github.com/onsi/gomega v1.30.0
|
||||||
github.com/opensearch-project/opensearch-go v1.1.0
|
github.com/opensearch-project/opensearch-go v1.1.0
|
||||||
github.com/prometheus/client_golang v1.18.0
|
github.com/prometheus/client_golang v1.18.0
|
||||||
github.com/spf13/cobra v1.8.0
|
github.com/spf13/cobra v1.8.0
|
||||||
|
@ -45,7 +45,7 @@ require (
|
||||||
k8s.io/component-base v0.29.4
|
k8s.io/component-base v0.29.4
|
||||||
k8s.io/component-helpers v0.29.4
|
k8s.io/component-helpers v0.29.4
|
||||||
k8s.io/controller-manager v0.29.4
|
k8s.io/controller-manager v0.29.4
|
||||||
k8s.io/klog/v2 v2.110.1
|
k8s.io/klog/v2 v2.120.0
|
||||||
k8s.io/kube-aggregator v0.29.4
|
k8s.io/kube-aggregator v0.29.4
|
||||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00
|
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00
|
||||||
k8s.io/kubectl v0.29.4
|
k8s.io/kubectl v0.29.4
|
||||||
|
@ -57,7 +57,7 @@ require (
|
||||||
sigs.k8s.io/custom-metrics-apiserver v1.29.0
|
sigs.k8s.io/custom-metrics-apiserver v1.29.0
|
||||||
sigs.k8s.io/kind v0.22.0
|
sigs.k8s.io/kind v0.22.0
|
||||||
sigs.k8s.io/mcs-api v0.1.0
|
sigs.k8s.io/mcs-api v0.1.0
|
||||||
sigs.k8s.io/metrics-server v0.6.1-0.20230706083104-796fc0f832c1
|
sigs.k8s.io/metrics-server v0.7.1
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1
|
sigs.k8s.io/structured-merge-diff/v4 v4.4.1
|
||||||
sigs.k8s.io/yaml v1.4.0
|
sigs.k8s.io/yaml v1.4.0
|
||||||
)
|
)
|
||||||
|
@ -79,7 +79,7 @@ require (
|
||||||
github.com/coreos/go-semver v0.3.1 // indirect
|
github.com/coreos/go-semver v0.3.1 // indirect
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||||
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
|
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
|
||||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
||||||
|
@ -101,7 +101,7 @@ require (
|
||||||
github.com/google/cel-go v0.17.7 // indirect
|
github.com/google/cel-go v0.17.7 // indirect
|
||||||
github.com/google/gnostic-models v0.6.8 // indirect
|
github.com/google/gnostic-models v0.6.8 // indirect
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
|
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 // indirect
|
||||||
github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect
|
github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 // indirect
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
github.com/gorilla/websocket v1.5.0 // indirect
|
github.com/gorilla/websocket v1.5.0 // indirect
|
||||||
|
@ -120,7 +120,6 @@ require (
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.17 // indirect
|
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
|
@ -137,7 +136,7 @@ require (
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_model v0.5.0 // indirect
|
github.com/prometheus/client_model v0.5.0 // indirect
|
||||||
github.com/prometheus/common v0.45.0 // indirect
|
github.com/prometheus/common v0.46.0 // indirect
|
||||||
github.com/prometheus/procfs v0.12.0 // indirect
|
github.com/prometheus/procfs v0.12.0 // indirect
|
||||||
github.com/rivo/uniseg v0.4.2 // indirect
|
github.com/rivo/uniseg v0.4.2 // indirect
|
||||||
github.com/robfig/cron/v3 v3.0.1 // indirect
|
github.com/robfig/cron/v3 v3.0.1 // indirect
|
||||||
|
@ -167,13 +166,13 @@ require (
|
||||||
go.opentelemetry.io/otel/trace v1.21.0 // indirect
|
go.opentelemetry.io/otel/trace v1.21.0 // indirect
|
||||||
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
||||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
|
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
|
||||||
go.uber.org/atomic v1.10.0 // indirect
|
go.uber.org/atomic v1.11.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.26.0 // indirect
|
go.uber.org/zap v1.26.0 // indirect
|
||||||
golang.org/x/crypto v0.21.0 // indirect
|
golang.org/x/crypto v0.21.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20231226003508-02704c960a9b // indirect
|
golang.org/x/exp v0.0.0-20231226003508-02704c960a9b // indirect
|
||||||
golang.org/x/mod v0.14.0 // indirect
|
golang.org/x/mod v0.14.0 // indirect
|
||||||
golang.org/x/oauth2 v0.15.0 // indirect
|
golang.org/x/oauth2 v0.16.0 // indirect
|
||||||
golang.org/x/sync v0.5.0 // indirect
|
golang.org/x/sync v0.5.0 // indirect
|
||||||
golang.org/x/sys v0.18.0 // indirect
|
golang.org/x/sys v0.18.0 // indirect
|
||||||
google.golang.org/appengine v1.6.8 // indirect
|
google.golang.org/appengine v1.6.8 // indirect
|
||||||
|
|
37
go.sum
37
go.sum
|
@ -174,8 +174,9 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
||||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
|
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
|
||||||
|
@ -253,7 +254,6 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7
|
||||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||||
github.com/go-logr/logr v1.2.2/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.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
|
||||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
@ -405,8 +405,9 @@ github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLe
|
||||||
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
|
|
||||||
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||||
|
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ=
|
||||||
|
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 h1:SJ+NtwL6QaZ21U+IrK7d0gGgpjGGvd2kz+FzTHVzdqI=
|
github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2 h1:SJ+NtwL6QaZ21U+IrK7d0gGgpjGGvd2kz+FzTHVzdqI=
|
||||||
github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2/go.mod h1:Tv1PlzqC9t8wNnpPdctvtSUOPUUg4SHeE6vR1Ir2hmg=
|
github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2/go.mod h1:Tv1PlzqC9t8wNnpPdctvtSUOPUUg4SHeE6vR1Ir2hmg=
|
||||||
|
@ -560,8 +561,6 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
|
||||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
|
|
||||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
|
|
||||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
||||||
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
|
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
|
||||||
|
@ -606,15 +605,15 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
||||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||||
github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
|
github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY=
|
||||||
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
|
github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw=
|
||||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
|
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
|
||||||
github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
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/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/opensearch-project/opensearch-go v1.1.0 h1:eG5sh3843bbU1itPRjA9QXbxcg8LaZ+DjEzQH9aLN3M=
|
github.com/opensearch-project/opensearch-go v1.1.0 h1:eG5sh3843bbU1itPRjA9QXbxcg8LaZ+DjEzQH9aLN3M=
|
||||||
|
@ -658,8 +657,8 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q
|
||||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||||
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
||||||
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
|
github.com/prometheus/common v0.46.0 h1:doXzt5ybi1HBKpsZOL0sSkaNHJJqkyfEWZGGqqScV0Y=
|
||||||
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
|
github.com/prometheus/common v0.46.0/go.mod h1:Tp0qkxpb9Jsg54QMe+EAmqXkSV7Evdy1BTn+g2pa/hQ=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/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-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
@ -855,8 +854,8 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
|
@ -1013,8 +1012,8 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
|
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||||
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
|
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
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-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
@ -1473,8 +1472,8 @@ k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
|
||||||
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||||
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
|
k8s.io/klog/v2 v2.120.0 h1:z+q5mfovBj1fKFxiRzsa2DsJLPIVMk/KFL81LMOfK+8=
|
||||||
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
|
k8s.io/klog/v2 v2.120.0/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||||
k8s.io/kms v0.29.4 h1:cFGEoCLwoXk/eqYZppLZxybCdmEWeRKMCbm9f13IdRQ=
|
k8s.io/kms v0.29.4 h1:cFGEoCLwoXk/eqYZppLZxybCdmEWeRKMCbm9f13IdRQ=
|
||||||
k8s.io/kms v0.29.4/go.mod h1:vWVImKkJd+1BQY4tBwdfSwjQBiLrnbNtHADcDEDQFtk=
|
k8s.io/kms v0.29.4/go.mod h1:vWVImKkJd+1BQY4tBwdfSwjQBiLrnbNtHADcDEDQFtk=
|
||||||
k8s.io/kube-aggregator v0.29.4 h1:yT7vYtwIag4G8HNrktYZ3qz6p6oHKronMAXOw4eQ2WQ=
|
k8s.io/kube-aggregator v0.29.4 h1:yT7vYtwIag4G8HNrktYZ3qz6p6oHKronMAXOw4eQ2WQ=
|
||||||
|
@ -1518,8 +1517,8 @@ sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM
|
||||||
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag=
|
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag=
|
||||||
sigs.k8s.io/mcs-api v0.1.0 h1:edDbg0oRGfXw8TmZjKYep06LcJLv/qcYLidejnUp0PM=
|
sigs.k8s.io/mcs-api v0.1.0 h1:edDbg0oRGfXw8TmZjKYep06LcJLv/qcYLidejnUp0PM=
|
||||||
sigs.k8s.io/mcs-api v0.1.0/go.mod h1:gGiAryeFNB4GBsq2LBmVqSgKoobLxt+p7ii/WG5QYYw=
|
sigs.k8s.io/mcs-api v0.1.0/go.mod h1:gGiAryeFNB4GBsq2LBmVqSgKoobLxt+p7ii/WG5QYYw=
|
||||||
sigs.k8s.io/metrics-server v0.6.1-0.20230706083104-796fc0f832c1 h1:lAEAFgoTv5dM5A9cl2iUY8ro8l+4PViOkN9Oc4wTzow=
|
sigs.k8s.io/metrics-server v0.7.1 h1:LhdCzkaI7VI7/N7pR4hDauTuWyc9Pxr+ihjTDuS9GIo=
|
||||||
sigs.k8s.io/metrics-server v0.6.1-0.20230706083104-796fc0f832c1/go.mod h1:eYoM0c4p7XoWkUWzztpAydqkHRRblo4luZY8ex9fxcA=
|
sigs.k8s.io/metrics-server v0.7.1/go.mod h1:vt+pIEbw5tpmyRR46WJb3pRm1JEzf/HxRN+VClTKuqI=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
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 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
//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.
|
|
||||||
//
|
|
||||||
// Deprecated: use the main logr package instead.
|
|
||||||
package slogr
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log/slog"
|
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewLogr returns a logr.Logger which writes to the slog.Handler.
|
|
||||||
//
|
|
||||||
// Deprecated: use [logr.FromSlogHandler] instead.
|
|
||||||
func NewLogr(handler slog.Handler) logr.Logger {
|
|
||||||
return logr.FromSlogHandler(handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewSlogHandler returns a slog.Handler which writes to the same sink as the logr.Logger.
|
|
||||||
//
|
|
||||||
// Deprecated: use [logr.ToSlogHandler] instead.
|
|
||||||
func NewSlogHandler(logger logr.Logger) slog.Handler {
|
|
||||||
return logr.ToSlogHandler(logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToSlogHandler returns a slog.Handler which writes to the same sink as the logr.Logger.
|
|
||||||
//
|
|
||||||
// Deprecated: use [logr.ToSlogHandler] instead.
|
|
||||||
func ToSlogHandler(logger logr.Logger) slog.Handler {
|
|
||||||
return logr.ToSlogHandler(logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
// SlogSink is an optional interface that a LogSink can implement to support
|
|
||||||
// logging through the slog.Logger or slog.Handler APIs better.
|
|
||||||
//
|
|
||||||
// Deprecated: use [logr.SlogSink] instead.
|
|
||||||
type SlogSink = logr.SlogSink
|
|
|
@ -17,6 +17,7 @@ package profile
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *Profile) decoder() []decoder {
|
func (p *Profile) decoder() []decoder {
|
||||||
|
@ -183,12 +184,13 @@ var profileDecoder = []decoder{
|
||||||
// repeated Location location = 4
|
// repeated Location location = 4
|
||||||
func(b *buffer, m message) error {
|
func(b *buffer, m message) error {
|
||||||
x := new(Location)
|
x := new(Location)
|
||||||
x.Line = make([]Line, 0, 8) // Pre-allocate Line buffer
|
x.Line = b.tmpLines[:0] // Use shared space temporarily
|
||||||
pp := m.(*Profile)
|
pp := m.(*Profile)
|
||||||
pp.Location = append(pp.Location, x)
|
pp.Location = append(pp.Location, x)
|
||||||
err := decodeMessage(b, x)
|
err := decodeMessage(b, x)
|
||||||
var tmp []Line
|
b.tmpLines = x.Line[:0]
|
||||||
x.Line = append(tmp, x.Line...) // Shrink to allocated size
|
// Copy to shrink size and detach from shared space.
|
||||||
|
x.Line = append([]Line(nil), x.Line...)
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
// repeated Function function = 5
|
// repeated Function function = 5
|
||||||
|
@ -252,6 +254,14 @@ func (p *Profile) postDecode() error {
|
||||||
} else {
|
} else {
|
||||||
mappings[m.ID] = m
|
mappings[m.ID] = m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this a main linux kernel mapping with a relocation symbol suffix
|
||||||
|
// ("[kernel.kallsyms]_text"), extract said suffix.
|
||||||
|
// It is fairly hacky to handle at this level, but the alternatives appear even worse.
|
||||||
|
const prefix = "[kernel.kallsyms]"
|
||||||
|
if strings.HasPrefix(m.File, prefix) {
|
||||||
|
m.KernelRelocationSymbol = m.File[len(prefix):]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
functions := make(map[uint64]*Function, len(p.Function))
|
functions := make(map[uint64]*Function, len(p.Function))
|
||||||
|
@ -298,41 +308,52 @@ func (p *Profile) postDecode() error {
|
||||||
st.Unit, err = getString(p.stringTable, &st.unitX, err)
|
st.Unit, err = getString(p.stringTable, &st.unitX, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pre-allocate space for all locations.
|
||||||
|
numLocations := 0
|
||||||
for _, s := range p.Sample {
|
for _, s := range p.Sample {
|
||||||
labels := make(map[string][]string, len(s.labelX))
|
numLocations += len(s.locationIDX)
|
||||||
numLabels := make(map[string][]int64, len(s.labelX))
|
}
|
||||||
numUnits := make(map[string][]string, len(s.labelX))
|
locBuffer := make([]*Location, numLocations)
|
||||||
for _, l := range s.labelX {
|
|
||||||
var key, value string
|
for _, s := range p.Sample {
|
||||||
key, err = getString(p.stringTable, &l.keyX, err)
|
if len(s.labelX) > 0 {
|
||||||
if l.strX != 0 {
|
labels := make(map[string][]string, len(s.labelX))
|
||||||
value, err = getString(p.stringTable, &l.strX, err)
|
numLabels := make(map[string][]int64, len(s.labelX))
|
||||||
labels[key] = append(labels[key], value)
|
numUnits := make(map[string][]string, len(s.labelX))
|
||||||
} else if l.numX != 0 || l.unitX != 0 {
|
for _, l := range s.labelX {
|
||||||
numValues := numLabels[key]
|
var key, value string
|
||||||
units := numUnits[key]
|
key, err = getString(p.stringTable, &l.keyX, err)
|
||||||
if l.unitX != 0 {
|
if l.strX != 0 {
|
||||||
var unit string
|
value, err = getString(p.stringTable, &l.strX, err)
|
||||||
unit, err = getString(p.stringTable, &l.unitX, err)
|
labels[key] = append(labels[key], value)
|
||||||
units = padStringArray(units, len(numValues))
|
} else if l.numX != 0 || l.unitX != 0 {
|
||||||
numUnits[key] = append(units, unit)
|
numValues := numLabels[key]
|
||||||
}
|
units := numUnits[key]
|
||||||
numLabels[key] = append(numLabels[key], l.numX)
|
if l.unitX != 0 {
|
||||||
}
|
var unit string
|
||||||
}
|
unit, err = getString(p.stringTable, &l.unitX, err)
|
||||||
if len(labels) > 0 {
|
units = padStringArray(units, len(numValues))
|
||||||
s.Label = labels
|
numUnits[key] = append(units, unit)
|
||||||
}
|
}
|
||||||
if len(numLabels) > 0 {
|
numLabels[key] = append(numLabels[key], l.numX)
|
||||||
s.NumLabel = numLabels
|
|
||||||
for key, units := range numUnits {
|
|
||||||
if len(units) > 0 {
|
|
||||||
numUnits[key] = padStringArray(units, len(numLabels[key]))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.NumUnit = numUnits
|
if len(labels) > 0 {
|
||||||
|
s.Label = labels
|
||||||
|
}
|
||||||
|
if len(numLabels) > 0 {
|
||||||
|
s.NumLabel = numLabels
|
||||||
|
for key, units := range numUnits {
|
||||||
|
if len(units) > 0 {
|
||||||
|
numUnits[key] = padStringArray(units, len(numLabels[key]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.NumUnit = numUnits
|
||||||
|
}
|
||||||
}
|
}
|
||||||
s.Location = make([]*Location, len(s.locationIDX))
|
|
||||||
|
s.Location = locBuffer[:len(s.locationIDX)]
|
||||||
|
locBuffer = locBuffer[len(s.locationIDX):]
|
||||||
for i, lid := range s.locationIDX {
|
for i, lid := range s.locationIDX {
|
||||||
if lid < uint64(len(locationIds)) {
|
if lid < uint64(len(locationIds)) {
|
||||||
s.Location[i] = locationIds[lid]
|
s.Location[i] = locationIds[lid]
|
||||||
|
|
|
@ -22,6 +22,10 @@ import "regexp"
|
||||||
// samples where at least one frame matches focus but none match ignore.
|
// samples where at least one frame matches focus but none match ignore.
|
||||||
// Returns true is the corresponding regexp matched at least one sample.
|
// Returns true is the corresponding regexp matched at least one sample.
|
||||||
func (p *Profile) FilterSamplesByName(focus, ignore, hide, show *regexp.Regexp) (fm, im, hm, hnm bool) {
|
func (p *Profile) FilterSamplesByName(focus, ignore, hide, show *regexp.Regexp) (fm, im, hm, hnm bool) {
|
||||||
|
if focus == nil && ignore == nil && hide == nil && show == nil {
|
||||||
|
fm = true // Missing focus implies a match
|
||||||
|
return
|
||||||
|
}
|
||||||
focusOrIgnore := make(map[uint64]bool)
|
focusOrIgnore := make(map[uint64]bool)
|
||||||
hidden := make(map[uint64]bool)
|
hidden := make(map[uint64]bool)
|
||||||
for _, l := range p.Location {
|
for _, l := range p.Location {
|
||||||
|
|
|
@ -295,11 +295,12 @@ func get64b(b []byte) (uint64, []byte) {
|
||||||
//
|
//
|
||||||
// The general format for profilez samples is a sequence of words in
|
// The general format for profilez samples is a sequence of words in
|
||||||
// binary format. The first words are a header with the following data:
|
// binary format. The first words are a header with the following data:
|
||||||
// 1st word -- 0
|
//
|
||||||
// 2nd word -- 3
|
// 1st word -- 0
|
||||||
// 3rd word -- 0 if a c++ application, 1 if a java application.
|
// 2nd word -- 3
|
||||||
// 4th word -- Sampling period (in microseconds).
|
// 3rd word -- 0 if a c++ application, 1 if a java application.
|
||||||
// 5th word -- Padding.
|
// 4th word -- Sampling period (in microseconds).
|
||||||
|
// 5th word -- Padding.
|
||||||
func parseCPU(b []byte) (*Profile, error) {
|
func parseCPU(b []byte) (*Profile, error) {
|
||||||
var parse func([]byte) (uint64, []byte)
|
var parse func([]byte) (uint64, []byte)
|
||||||
var n1, n2, n3, n4, n5 uint64
|
var n1, n2, n3, n4, n5 uint64
|
||||||
|
@ -403,15 +404,18 @@ func cleanupDuplicateLocations(p *Profile) {
|
||||||
//
|
//
|
||||||
// profilez samples are a repeated sequence of stack frames of the
|
// profilez samples are a repeated sequence of stack frames of the
|
||||||
// form:
|
// form:
|
||||||
// 1st word -- The number of times this stack was encountered.
|
//
|
||||||
// 2nd word -- The size of the stack (StackSize).
|
// 1st word -- The number of times this stack was encountered.
|
||||||
// 3rd word -- The first address on the stack.
|
// 2nd word -- The size of the stack (StackSize).
|
||||||
// ...
|
// 3rd word -- The first address on the stack.
|
||||||
// StackSize + 2 -- The last address on the stack
|
// ...
|
||||||
|
// StackSize + 2 -- The last address on the stack
|
||||||
|
//
|
||||||
// The last stack trace is of the form:
|
// The last stack trace is of the form:
|
||||||
// 1st word -- 0
|
//
|
||||||
// 2nd word -- 1
|
// 1st word -- 0
|
||||||
// 3rd word -- 0
|
// 2nd word -- 1
|
||||||
|
// 3rd word -- 0
|
||||||
//
|
//
|
||||||
// Addresses from stack traces may point to the next instruction after
|
// Addresses from stack traces may point to the next instruction after
|
||||||
// each call. Optionally adjust by -1 to land somewhere on the actual
|
// each call. Optionally adjust by -1 to land somewhere on the actual
|
||||||
|
@ -861,7 +865,6 @@ func parseThread(b []byte) (*Profile, error) {
|
||||||
// Recognize each thread and populate profile samples.
|
// Recognize each thread and populate profile samples.
|
||||||
for !isMemoryMapSentinel(line) {
|
for !isMemoryMapSentinel(line) {
|
||||||
if strings.HasPrefix(line, "---- no stack trace for") {
|
if strings.HasPrefix(line, "---- no stack trace for") {
|
||||||
line = ""
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if t := threadStartRE.FindStringSubmatch(line); len(t) != 4 {
|
if t := threadStartRE.FindStringSubmatch(line); len(t) != 4 {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
package profile
|
package profile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -58,7 +59,7 @@ func Merge(srcs []*Profile) (*Profile, error) {
|
||||||
|
|
||||||
for _, src := range srcs {
|
for _, src := range srcs {
|
||||||
// Clear the profile-specific hash tables
|
// Clear the profile-specific hash tables
|
||||||
pm.locationsByID = make(map[uint64]*Location, len(src.Location))
|
pm.locationsByID = makeLocationIDMap(len(src.Location))
|
||||||
pm.functionsByID = make(map[uint64]*Function, len(src.Function))
|
pm.functionsByID = make(map[uint64]*Function, len(src.Function))
|
||||||
pm.mappingsByID = make(map[uint64]mapInfo, len(src.Mapping))
|
pm.mappingsByID = make(map[uint64]mapInfo, len(src.Mapping))
|
||||||
|
|
||||||
|
@ -136,7 +137,7 @@ type profileMerger struct {
|
||||||
p *Profile
|
p *Profile
|
||||||
|
|
||||||
// Memoization tables within a profile.
|
// Memoization tables within a profile.
|
||||||
locationsByID map[uint64]*Location
|
locationsByID locationIDMap
|
||||||
functionsByID map[uint64]*Function
|
functionsByID map[uint64]*Function
|
||||||
mappingsByID map[uint64]mapInfo
|
mappingsByID map[uint64]mapInfo
|
||||||
|
|
||||||
|
@ -153,6 +154,16 @@ type mapInfo struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pm *profileMerger) mapSample(src *Sample) *Sample {
|
func (pm *profileMerger) mapSample(src *Sample) *Sample {
|
||||||
|
// Check memoization table
|
||||||
|
k := pm.sampleKey(src)
|
||||||
|
if ss, ok := pm.samples[k]; ok {
|
||||||
|
for i, v := range src.Value {
|
||||||
|
ss.Value[i] += v
|
||||||
|
}
|
||||||
|
return ss
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make new sample.
|
||||||
s := &Sample{
|
s := &Sample{
|
||||||
Location: make([]*Location, len(src.Location)),
|
Location: make([]*Location, len(src.Location)),
|
||||||
Value: make([]int64, len(src.Value)),
|
Value: make([]int64, len(src.Value)),
|
||||||
|
@ -177,52 +188,98 @@ func (pm *profileMerger) mapSample(src *Sample) *Sample {
|
||||||
s.NumLabel[k] = vv
|
s.NumLabel[k] = vv
|
||||||
s.NumUnit[k] = uu
|
s.NumUnit[k] = uu
|
||||||
}
|
}
|
||||||
// Check memoization table. Must be done on the remapped location to
|
|
||||||
// account for the remapped mapping. Add current values to the
|
|
||||||
// existing sample.
|
|
||||||
k := s.key()
|
|
||||||
if ss, ok := pm.samples[k]; ok {
|
|
||||||
for i, v := range src.Value {
|
|
||||||
ss.Value[i] += v
|
|
||||||
}
|
|
||||||
return ss
|
|
||||||
}
|
|
||||||
copy(s.Value, src.Value)
|
copy(s.Value, src.Value)
|
||||||
pm.samples[k] = s
|
pm.samples[k] = s
|
||||||
pm.p.Sample = append(pm.p.Sample, s)
|
pm.p.Sample = append(pm.p.Sample, s)
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// key generates sampleKey to be used as a key for maps.
|
func (pm *profileMerger) sampleKey(sample *Sample) sampleKey {
|
||||||
func (sample *Sample) key() sampleKey {
|
// Accumulate contents into a string.
|
||||||
ids := make([]string, len(sample.Location))
|
var buf strings.Builder
|
||||||
for i, l := range sample.Location {
|
buf.Grow(64) // Heuristic to avoid extra allocs
|
||||||
ids[i] = strconv.FormatUint(l.ID, 16)
|
|
||||||
|
// encode a number
|
||||||
|
putNumber := func(v uint64) {
|
||||||
|
var num [binary.MaxVarintLen64]byte
|
||||||
|
n := binary.PutUvarint(num[:], v)
|
||||||
|
buf.Write(num[:n])
|
||||||
}
|
}
|
||||||
|
|
||||||
labels := make([]string, 0, len(sample.Label))
|
// encode a string prefixed with its length.
|
||||||
for k, v := range sample.Label {
|
putDelimitedString := func(s string) {
|
||||||
labels = append(labels, fmt.Sprintf("%q%q", k, v))
|
putNumber(uint64(len(s)))
|
||||||
|
buf.WriteString(s)
|
||||||
}
|
}
|
||||||
sort.Strings(labels)
|
|
||||||
|
|
||||||
numlabels := make([]string, 0, len(sample.NumLabel))
|
for _, l := range sample.Location {
|
||||||
for k, v := range sample.NumLabel {
|
// Get the location in the merged profile, which may have a different ID.
|
||||||
numlabels = append(numlabels, fmt.Sprintf("%q%x%x", k, v, sample.NumUnit[k]))
|
if loc := pm.mapLocation(l); loc != nil {
|
||||||
|
putNumber(loc.ID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
sort.Strings(numlabels)
|
putNumber(0) // Delimiter
|
||||||
|
|
||||||
return sampleKey{
|
for _, l := range sortedKeys1(sample.Label) {
|
||||||
strings.Join(ids, "|"),
|
putDelimitedString(l)
|
||||||
strings.Join(labels, ""),
|
values := sample.Label[l]
|
||||||
strings.Join(numlabels, ""),
|
putNumber(uint64(len(values)))
|
||||||
|
for _, v := range values {
|
||||||
|
putDelimitedString(v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, l := range sortedKeys2(sample.NumLabel) {
|
||||||
|
putDelimitedString(l)
|
||||||
|
values := sample.NumLabel[l]
|
||||||
|
putNumber(uint64(len(values)))
|
||||||
|
for _, v := range values {
|
||||||
|
putNumber(uint64(v))
|
||||||
|
}
|
||||||
|
units := sample.NumUnit[l]
|
||||||
|
putNumber(uint64(len(units)))
|
||||||
|
for _, v := range units {
|
||||||
|
putDelimitedString(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sampleKey(buf.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
type sampleKey struct {
|
type sampleKey string
|
||||||
locations string
|
|
||||||
labels string
|
// sortedKeys1 returns the sorted keys found in a string->[]string map.
|
||||||
numlabels string
|
//
|
||||||
|
// Note: this is currently non-generic since github pprof runs golint,
|
||||||
|
// which does not support generics. When that issue is fixed, it can
|
||||||
|
// be merged with sortedKeys2 and made into a generic function.
|
||||||
|
func sortedKeys1(m map[string][]string) []string {
|
||||||
|
if len(m) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
keys := make([]string, 0, len(m))
|
||||||
|
for k := range m {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
// sortedKeys2 returns the sorted keys found in a string->[]int64 map.
|
||||||
|
//
|
||||||
|
// Note: this is currently non-generic since github pprof runs golint,
|
||||||
|
// which does not support generics. When that issue is fixed, it can
|
||||||
|
// be merged with sortedKeys1 and made into a generic function.
|
||||||
|
func sortedKeys2(m map[string][]int64) []string {
|
||||||
|
if len(m) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
keys := make([]string, 0, len(m))
|
||||||
|
for k := range m {
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pm *profileMerger) mapLocation(src *Location) *Location {
|
func (pm *profileMerger) mapLocation(src *Location) *Location {
|
||||||
|
@ -230,7 +287,7 @@ func (pm *profileMerger) mapLocation(src *Location) *Location {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if l, ok := pm.locationsByID[src.ID]; ok {
|
if l := pm.locationsByID.get(src.ID); l != nil {
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,10 +306,10 @@ func (pm *profileMerger) mapLocation(src *Location) *Location {
|
||||||
// account for the remapped mapping ID.
|
// account for the remapped mapping ID.
|
||||||
k := l.key()
|
k := l.key()
|
||||||
if ll, ok := pm.locations[k]; ok {
|
if ll, ok := pm.locations[k]; ok {
|
||||||
pm.locationsByID[src.ID] = ll
|
pm.locationsByID.set(src.ID, ll)
|
||||||
return ll
|
return ll
|
||||||
}
|
}
|
||||||
pm.locationsByID[src.ID] = l
|
pm.locationsByID.set(src.ID, l)
|
||||||
pm.locations[k] = l
|
pm.locations[k] = l
|
||||||
pm.p.Location = append(pm.p.Location, l)
|
pm.p.Location = append(pm.p.Location, l)
|
||||||
return l
|
return l
|
||||||
|
@ -303,16 +360,17 @@ func (pm *profileMerger) mapMapping(src *Mapping) mapInfo {
|
||||||
return mi
|
return mi
|
||||||
}
|
}
|
||||||
m := &Mapping{
|
m := &Mapping{
|
||||||
ID: uint64(len(pm.p.Mapping) + 1),
|
ID: uint64(len(pm.p.Mapping) + 1),
|
||||||
Start: src.Start,
|
Start: src.Start,
|
||||||
Limit: src.Limit,
|
Limit: src.Limit,
|
||||||
Offset: src.Offset,
|
Offset: src.Offset,
|
||||||
File: src.File,
|
File: src.File,
|
||||||
BuildID: src.BuildID,
|
KernelRelocationSymbol: src.KernelRelocationSymbol,
|
||||||
HasFunctions: src.HasFunctions,
|
BuildID: src.BuildID,
|
||||||
HasFilenames: src.HasFilenames,
|
HasFunctions: src.HasFunctions,
|
||||||
HasLineNumbers: src.HasLineNumbers,
|
HasFilenames: src.HasFilenames,
|
||||||
HasInlineFrames: src.HasInlineFrames,
|
HasLineNumbers: src.HasLineNumbers,
|
||||||
|
HasInlineFrames: src.HasInlineFrames,
|
||||||
}
|
}
|
||||||
pm.p.Mapping = append(pm.p.Mapping, m)
|
pm.p.Mapping = append(pm.p.Mapping, m)
|
||||||
|
|
||||||
|
@ -479,3 +537,131 @@ func (p *Profile) compatible(pb *Profile) error {
|
||||||
func equalValueType(st1, st2 *ValueType) bool {
|
func equalValueType(st1, st2 *ValueType) bool {
|
||||||
return st1.Type == st2.Type && st1.Unit == st2.Unit
|
return st1.Type == st2.Type && st1.Unit == st2.Unit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// locationIDMap is like a map[uint64]*Location, but provides efficiency for
|
||||||
|
// ids that are densely numbered, which is often the case.
|
||||||
|
type locationIDMap struct {
|
||||||
|
dense []*Location // indexed by id for id < len(dense)
|
||||||
|
sparse map[uint64]*Location // indexed by id for id >= len(dense)
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeLocationIDMap(n int) locationIDMap {
|
||||||
|
return locationIDMap{
|
||||||
|
dense: make([]*Location, n),
|
||||||
|
sparse: map[uint64]*Location{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lm locationIDMap) get(id uint64) *Location {
|
||||||
|
if id < uint64(len(lm.dense)) {
|
||||||
|
return lm.dense[int(id)]
|
||||||
|
}
|
||||||
|
return lm.sparse[id]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (lm locationIDMap) set(id uint64, loc *Location) {
|
||||||
|
if id < uint64(len(lm.dense)) {
|
||||||
|
lm.dense[id] = loc
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lm.sparse[id] = loc
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompatibilizeSampleTypes makes profiles compatible to be compared/merged. It
|
||||||
|
// keeps sample types that appear in all profiles only and drops/reorders the
|
||||||
|
// sample types as necessary.
|
||||||
|
//
|
||||||
|
// In the case of sample types order is not the same for given profiles the
|
||||||
|
// order is derived from the first profile.
|
||||||
|
//
|
||||||
|
// Profiles are modified in-place.
|
||||||
|
//
|
||||||
|
// It returns an error if the sample type's intersection is empty.
|
||||||
|
func CompatibilizeSampleTypes(ps []*Profile) error {
|
||||||
|
sTypes := commonSampleTypes(ps)
|
||||||
|
if len(sTypes) == 0 {
|
||||||
|
return fmt.Errorf("profiles have empty common sample type list")
|
||||||
|
}
|
||||||
|
for _, p := range ps {
|
||||||
|
if err := compatibilizeSampleTypes(p, sTypes); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// commonSampleTypes returns sample types that appear in all profiles in the
|
||||||
|
// order how they ordered in the first profile.
|
||||||
|
func commonSampleTypes(ps []*Profile) []string {
|
||||||
|
if len(ps) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
sTypes := map[string]int{}
|
||||||
|
for _, p := range ps {
|
||||||
|
for _, st := range p.SampleType {
|
||||||
|
sTypes[st.Type]++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var res []string
|
||||||
|
for _, st := range ps[0].SampleType {
|
||||||
|
if sTypes[st.Type] == len(ps) {
|
||||||
|
res = append(res, st.Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// compatibilizeSampleTypes drops sample types that are not present in sTypes
|
||||||
|
// list and reorder them if needed.
|
||||||
|
//
|
||||||
|
// It sets DefaultSampleType to sType[0] if it is not in sType list.
|
||||||
|
//
|
||||||
|
// It assumes that all sample types from the sTypes list are present in the
|
||||||
|
// given profile otherwise it returns an error.
|
||||||
|
func compatibilizeSampleTypes(p *Profile, sTypes []string) error {
|
||||||
|
if len(sTypes) == 0 {
|
||||||
|
return fmt.Errorf("sample type list is empty")
|
||||||
|
}
|
||||||
|
defaultSampleType := sTypes[0]
|
||||||
|
reMap, needToModify := make([]int, len(sTypes)), false
|
||||||
|
for i, st := range sTypes {
|
||||||
|
if st == p.DefaultSampleType {
|
||||||
|
defaultSampleType = p.DefaultSampleType
|
||||||
|
}
|
||||||
|
idx := searchValueType(p.SampleType, st)
|
||||||
|
if idx < 0 {
|
||||||
|
return fmt.Errorf("%q sample type is not found in profile", st)
|
||||||
|
}
|
||||||
|
reMap[i] = idx
|
||||||
|
if idx != i {
|
||||||
|
needToModify = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !needToModify && len(sTypes) == len(p.SampleType) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
p.DefaultSampleType = defaultSampleType
|
||||||
|
oldSampleTypes := p.SampleType
|
||||||
|
p.SampleType = make([]*ValueType, len(sTypes))
|
||||||
|
for i, idx := range reMap {
|
||||||
|
p.SampleType[i] = oldSampleTypes[idx]
|
||||||
|
}
|
||||||
|
values := make([]int64, len(sTypes))
|
||||||
|
for _, s := range p.Sample {
|
||||||
|
for i, idx := range reMap {
|
||||||
|
values[i] = s.Value[idx]
|
||||||
|
}
|
||||||
|
s.Value = s.Value[:len(values)]
|
||||||
|
copy(s.Value, values)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func searchValueType(vts []*ValueType, s string) int {
|
||||||
|
for i, vt := range vts {
|
||||||
|
if vt.Type == s {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"math"
|
"math"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -73,9 +72,23 @@ type ValueType struct {
|
||||||
type Sample struct {
|
type Sample struct {
|
||||||
Location []*Location
|
Location []*Location
|
||||||
Value []int64
|
Value []int64
|
||||||
Label map[string][]string
|
// Label is a per-label-key map to values for string labels.
|
||||||
|
//
|
||||||
|
// In general, having multiple values for the given label key is strongly
|
||||||
|
// discouraged - see docs for the sample label field in profile.proto. The
|
||||||
|
// main reason this unlikely state is tracked here is to make the
|
||||||
|
// decoding->encoding roundtrip not lossy. But we expect that the value
|
||||||
|
// slices present in this map are always of length 1.
|
||||||
|
Label map[string][]string
|
||||||
|
// NumLabel is a per-label-key map to values for numeric labels. See a note
|
||||||
|
// above on handling multiple values for a label.
|
||||||
NumLabel map[string][]int64
|
NumLabel map[string][]int64
|
||||||
NumUnit map[string][]string
|
// NumUnit is a per-label-key map to the unit names of corresponding numeric
|
||||||
|
// label values. The unit info may be missing even if the label is in
|
||||||
|
// NumLabel, see the docs in profile.proto for details. When the value is
|
||||||
|
// slice is present and not nil, its length must be equal to the length of
|
||||||
|
// the corresponding value slice in NumLabel.
|
||||||
|
NumUnit map[string][]string
|
||||||
|
|
||||||
locationIDX []uint64
|
locationIDX []uint64
|
||||||
labelX []label
|
labelX []label
|
||||||
|
@ -106,6 +119,15 @@ type Mapping struct {
|
||||||
|
|
||||||
fileX int64
|
fileX int64
|
||||||
buildIDX int64
|
buildIDX int64
|
||||||
|
|
||||||
|
// Name of the kernel relocation symbol ("_text" or "_stext"), extracted from File.
|
||||||
|
// For linux kernel mappings generated by some tools, correct symbolization depends
|
||||||
|
// on knowing which of the two possible relocation symbols was used for `Start`.
|
||||||
|
// This is given to us as a suffix in `File` (e.g. "[kernel.kallsyms]_stext").
|
||||||
|
//
|
||||||
|
// Note, this public field is not persisted in the proto. For the purposes of
|
||||||
|
// copying / merging / hashing profiles, it is considered subsumed by `File`.
|
||||||
|
KernelRelocationSymbol string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Location corresponds to Profile.Location
|
// Location corresponds to Profile.Location
|
||||||
|
@ -144,7 +166,7 @@ type Function struct {
|
||||||
// may be a gzip-compressed encoded protobuf or one of many legacy
|
// may be a gzip-compressed encoded protobuf or one of many legacy
|
||||||
// profile formats which may be unsupported in the future.
|
// profile formats which may be unsupported in the future.
|
||||||
func Parse(r io.Reader) (*Profile, error) {
|
func Parse(r io.Reader) (*Profile, error) {
|
||||||
data, err := ioutil.ReadAll(r)
|
data, err := io.ReadAll(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -159,7 +181,7 @@ func ParseData(data []byte) (*Profile, error) {
|
||||||
if len(data) >= 2 && data[0] == 0x1f && data[1] == 0x8b {
|
if len(data) >= 2 && data[0] == 0x1f && data[1] == 0x8b {
|
||||||
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
data, err = ioutil.ReadAll(gz)
|
data, err = io.ReadAll(gz)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("decompressing profile: %v", err)
|
return nil, fmt.Errorf("decompressing profile: %v", err)
|
||||||
|
@ -707,6 +729,35 @@ func (s *Sample) HasLabel(key, value string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetNumLabel sets the specified key to the specified value for all samples in the
|
||||||
|
// profile. "unit" is a slice that describes the units that each corresponding member
|
||||||
|
// of "values" is measured in (e.g. bytes or seconds). If there is no relevant
|
||||||
|
// unit for a given value, that member of "unit" should be the empty string.
|
||||||
|
// "unit" must either have the same length as "value", or be nil.
|
||||||
|
func (p *Profile) SetNumLabel(key string, value []int64, unit []string) {
|
||||||
|
for _, sample := range p.Sample {
|
||||||
|
if sample.NumLabel == nil {
|
||||||
|
sample.NumLabel = map[string][]int64{key: value}
|
||||||
|
} else {
|
||||||
|
sample.NumLabel[key] = value
|
||||||
|
}
|
||||||
|
if sample.NumUnit == nil {
|
||||||
|
sample.NumUnit = map[string][]string{key: unit}
|
||||||
|
} else {
|
||||||
|
sample.NumUnit[key] = unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoveNumLabel removes all numerical labels associated with the specified key for all
|
||||||
|
// samples in the profile.
|
||||||
|
func (p *Profile) RemoveNumLabel(key string) {
|
||||||
|
for _, sample := range p.Sample {
|
||||||
|
delete(sample.NumLabel, key)
|
||||||
|
delete(sample.NumUnit, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// DiffBaseSample returns true if a sample belongs to the diff base and false
|
// DiffBaseSample returns true if a sample belongs to the diff base and false
|
||||||
// otherwise.
|
// otherwise.
|
||||||
func (s *Sample) DiffBaseSample() bool {
|
func (s *Sample) DiffBaseSample() bool {
|
||||||
|
|
|
@ -39,11 +39,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type buffer struct {
|
type buffer struct {
|
||||||
field int // field tag
|
field int // field tag
|
||||||
typ int // proto wire type code for field
|
typ int // proto wire type code for field
|
||||||
u64 uint64
|
u64 uint64
|
||||||
data []byte
|
data []byte
|
||||||
tmp [16]byte
|
tmp [16]byte
|
||||||
|
tmpLines []Line // temporary storage used while decoding "repeated Line".
|
||||||
}
|
}
|
||||||
|
|
||||||
type decoder func(*buffer, message) error
|
type decoder func(*buffer, message) error
|
||||||
|
@ -286,7 +287,6 @@ func decodeInt64s(b *buffer, x *[]int64) error {
|
||||||
if b.typ == 2 {
|
if b.typ == 2 {
|
||||||
// Packed encoding
|
// Packed encoding
|
||||||
data := b.data
|
data := b.data
|
||||||
tmp := make([]int64, 0, len(data)) // Maximally sized
|
|
||||||
for len(data) > 0 {
|
for len(data) > 0 {
|
||||||
var u uint64
|
var u uint64
|
||||||
var err error
|
var err error
|
||||||
|
@ -294,9 +294,8 @@ func decodeInt64s(b *buffer, x *[]int64) error {
|
||||||
if u, data, err = decodeVarint(data); err != nil {
|
if u, data, err = decodeVarint(data); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tmp = append(tmp, int64(u))
|
*x = append(*x, int64(u))
|
||||||
}
|
}
|
||||||
*x = append(*x, tmp...)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var i int64
|
var i int64
|
||||||
|
@ -319,7 +318,6 @@ func decodeUint64s(b *buffer, x *[]uint64) error {
|
||||||
if b.typ == 2 {
|
if b.typ == 2 {
|
||||||
data := b.data
|
data := b.data
|
||||||
// Packed encoding
|
// Packed encoding
|
||||||
tmp := make([]uint64, 0, len(data)) // Maximally sized
|
|
||||||
for len(data) > 0 {
|
for len(data) > 0 {
|
||||||
var u uint64
|
var u uint64
|
||||||
var err error
|
var err error
|
||||||
|
@ -327,9 +325,8 @@ func decodeUint64s(b *buffer, x *[]uint64) error {
|
||||||
if u, data, err = decodeVarint(data); err != nil {
|
if u, data, err = decodeVarint(data); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tmp = append(tmp, u)
|
*x = append(*x, u)
|
||||||
}
|
}
|
||||||
*x = append(*x, tmp...)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var u uint64
|
var u uint64
|
||||||
|
|
|
@ -62,15 +62,31 @@ func (p *Profile) Prune(dropRx, keepRx *regexp.Regexp) {
|
||||||
prune := make(map[uint64]bool)
|
prune := make(map[uint64]bool)
|
||||||
pruneBeneath := make(map[uint64]bool)
|
pruneBeneath := make(map[uint64]bool)
|
||||||
|
|
||||||
|
// simplifyFunc can be expensive, so cache results.
|
||||||
|
// Note that the same function name can be encountered many times due
|
||||||
|
// different lines and addresses in the same function.
|
||||||
|
pruneCache := map[string]bool{} // Map from function to whether or not to prune
|
||||||
|
pruneFromHere := func(s string) bool {
|
||||||
|
if r, ok := pruneCache[s]; ok {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
funcName := simplifyFunc(s)
|
||||||
|
if dropRx.MatchString(funcName) {
|
||||||
|
if keepRx == nil || !keepRx.MatchString(funcName) {
|
||||||
|
pruneCache[s] = true
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pruneCache[s] = false
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
for _, loc := range p.Location {
|
for _, loc := range p.Location {
|
||||||
var i int
|
var i int
|
||||||
for i = len(loc.Line) - 1; i >= 0; i-- {
|
for i = len(loc.Line) - 1; i >= 0; i-- {
|
||||||
if fn := loc.Line[i].Function; fn != nil && fn.Name != "" {
|
if fn := loc.Line[i].Function; fn != nil && fn.Name != "" {
|
||||||
funcName := simplifyFunc(fn.Name)
|
if pruneFromHere(fn.Name) {
|
||||||
if dropRx.MatchString(funcName) {
|
break
|
||||||
if keepRx == nil || !keepRx.MatchString(funcName) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,201 +0,0 @@
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright {yyyy} {name of copyright owner}
|
|
||||||
|
|
||||||
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.
|
|
|
@ -1 +0,0 @@
|
||||||
Copyright 2012 Matt T. Proud (matt.proud@gmail.com)
|
|
|
@ -1 +0,0 @@
|
||||||
cover.dat
|
|
|
@ -1,7 +0,0 @@
|
||||||
all:
|
|
||||||
|
|
||||||
cover:
|
|
||||||
go test -cover -v -coverprofile=cover.dat ./...
|
|
||||||
go tool cover -func cover.dat
|
|
||||||
|
|
||||||
.PHONY: cover
|
|
|
@ -1,81 +0,0 @@
|
||||||
// Copyright 2013 Matt T. Proud
|
|
||||||
//
|
|
||||||
// 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 pbutil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"errors"
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO: Give error package name prefix in next minor release.
|
|
||||||
var errInvalidVarint = errors.New("invalid varint32 encountered")
|
|
||||||
|
|
||||||
// ReadDelimited decodes a message from the provided length-delimited stream,
|
|
||||||
// where the length is encoded as 32-bit varint prefix to the message body.
|
|
||||||
// It returns the total number of bytes read and any applicable error. This is
|
|
||||||
// roughly equivalent to the companion Java API's
|
|
||||||
// MessageLite#parseDelimitedFrom. As per the reader contract, this function
|
|
||||||
// calls r.Read repeatedly as required until exactly one message including its
|
|
||||||
// prefix is read and decoded (or an error has occurred). The function never
|
|
||||||
// reads more bytes from the stream than required. The function never returns
|
|
||||||
// an error if a message has been read and decoded correctly, even if the end
|
|
||||||
// of the stream has been reached in doing so. In that case, any subsequent
|
|
||||||
// calls return (0, io.EOF).
|
|
||||||
func ReadDelimited(r io.Reader, m proto.Message) (n int, err error) {
|
|
||||||
// TODO: Consider allowing the caller to specify a decode buffer in the
|
|
||||||
// next major version.
|
|
||||||
|
|
||||||
// TODO: Consider using error wrapping to annotate error state in pass-
|
|
||||||
// through cases in the next minor version.
|
|
||||||
|
|
||||||
// Per AbstractParser#parsePartialDelimitedFrom with
|
|
||||||
// CodedInputStream#readRawVarint32.
|
|
||||||
var headerBuf [binary.MaxVarintLen32]byte
|
|
||||||
var bytesRead, varIntBytes int
|
|
||||||
var messageLength uint64
|
|
||||||
for varIntBytes == 0 { // i.e. no varint has been decoded yet.
|
|
||||||
if bytesRead >= len(headerBuf) {
|
|
||||||
return bytesRead, errInvalidVarint
|
|
||||||
}
|
|
||||||
// We have to read byte by byte here to avoid reading more bytes
|
|
||||||
// than required. Each read byte is appended to what we have
|
|
||||||
// read before.
|
|
||||||
newBytesRead, err := r.Read(headerBuf[bytesRead : bytesRead+1])
|
|
||||||
if newBytesRead == 0 {
|
|
||||||
if err != nil {
|
|
||||||
return bytesRead, err
|
|
||||||
}
|
|
||||||
// A Reader should not return (0, nil); but if it does, it should
|
|
||||||
// be treated as no-op according to the Reader contract.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
bytesRead += newBytesRead
|
|
||||||
// Now present everything read so far to the varint decoder and
|
|
||||||
// see if a varint can be decoded already.
|
|
||||||
messageLength, varIntBytes = binary.Uvarint(headerBuf[:bytesRead])
|
|
||||||
}
|
|
||||||
|
|
||||||
messageBuf := make([]byte, messageLength)
|
|
||||||
newBytesRead, err := io.ReadFull(r, messageBuf)
|
|
||||||
bytesRead += newBytesRead
|
|
||||||
if err != nil {
|
|
||||||
return bytesRead, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return bytesRead, proto.Unmarshal(messageBuf, m)
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
// Copyright 2013 Matt T. Proud
|
|
||||||
//
|
|
||||||
// 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 pbutil provides record length-delimited Protocol Buffer streaming.
|
|
||||||
package pbutil
|
|
|
@ -1,49 +0,0 @@
|
||||||
// Copyright 2013 Matt T. Proud
|
|
||||||
//
|
|
||||||
// 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 pbutil
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"io"
|
|
||||||
|
|
||||||
"google.golang.org/protobuf/proto"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WriteDelimited encodes and dumps a message to the provided writer prefixed
|
|
||||||
// with a 32-bit varint indicating the length of the encoded message, producing
|
|
||||||
// a length-delimited record stream, which can be used to chain together
|
|
||||||
// encoded messages of the same type together in a file. It returns the total
|
|
||||||
// number of bytes written and any applicable error. This is roughly
|
|
||||||
// equivalent to the companion Java API's MessageLite#writeDelimitedTo.
|
|
||||||
func WriteDelimited(w io.Writer, m proto.Message) (n int, err error) {
|
|
||||||
// TODO: Consider allowing the caller to specify an encode buffer in the
|
|
||||||
// next major version.
|
|
||||||
|
|
||||||
buffer, err := proto.Marshal(m)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf [binary.MaxVarintLen32]byte
|
|
||||||
encodedLength := binary.PutUvarint(buf[:], uint64(len(buffer)))
|
|
||||||
|
|
||||||
sync, err := w.Write(buf[:encodedLength])
|
|
||||||
if err != nil {
|
|
||||||
return sync, err
|
|
||||||
}
|
|
||||||
|
|
||||||
n, err = w.Write(buffer)
|
|
||||||
return n + sync, err
|
|
||||||
}
|
|
|
@ -1,3 +1,46 @@
|
||||||
|
## 2.14.0
|
||||||
|
|
||||||
|
### Features
|
||||||
|
You can now use `GinkgoTB()` when you need an instance of `testing.TB` to pass to a library.
|
||||||
|
|
||||||
|
Prior to this release table testing only supported generating individual `It`s for each test entry. `DescribeTableSubtree` extends table testing support to entire testing subtrees - under the hood `DescrieTableSubtree` generates a new container for each entry and invokes your function to fill our the container. See the [docs](https://onsi.github.io/ginkgo/#generating-subtree-tables) to learn more.
|
||||||
|
|
||||||
|
- Introduce DescribeTableSubtree [65ec56d]
|
||||||
|
- add GinkgoTB() to docs [4a2c832]
|
||||||
|
- Add GinkgoTB() function (#1333) [92b6744]
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix typo in internal/suite.go (#1332) [beb9507]
|
||||||
|
- Fix typo in docs/index.md (#1319) [4ac3a13]
|
||||||
|
- allow wasm to compile with ginkgo present (#1311) [b2e5bc5]
|
||||||
|
|
||||||
|
### Maintenance
|
||||||
|
- Bump golang.org/x/tools from 0.16.0 to 0.16.1 (#1316) [465a8ec]
|
||||||
|
- Bump actions/setup-go from 4 to 5 (#1313) [eab0e40]
|
||||||
|
- Bump github/codeql-action from 2 to 3 (#1317) [fbf9724]
|
||||||
|
- Bump golang.org/x/crypto (#1318) [3ee80ee]
|
||||||
|
- Bump golang.org/x/tools from 0.14.0 to 0.16.0 (#1306) [123e1d5]
|
||||||
|
- Bump github.com/onsi/gomega from 1.29.0 to 1.30.0 (#1297) [558f6e0]
|
||||||
|
- Bump golang.org/x/net from 0.17.0 to 0.19.0 (#1307) [84ff7f3]
|
||||||
|
|
||||||
|
## 2.13.2
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- Fix file handler leak (#1309) [e2e81c8]
|
||||||
|
- Avoid allocations with `(*regexp.Regexp).MatchString` (#1302) [3b2a2a7]
|
||||||
|
|
||||||
|
## 2.13.1
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
- # 1296 fix(precompiled test guite): exec bit check omitted on Windows (#1301) [26eea01]
|
||||||
|
|
||||||
|
### Maintenance
|
||||||
|
- Bump github.com/go-logr/logr from 1.2.4 to 1.3.0 (#1291) [7161a9d]
|
||||||
|
- Bump golang.org/x/sys from 0.13.0 to 0.14.0 (#1295) [7fc7b10]
|
||||||
|
- Bump golang.org/x/tools from 0.12.0 to 0.14.0 (#1282) [74bbd65]
|
||||||
|
- Bump github.com/onsi/gomega from 1.27.10 to 1.29.0 (#1290) [9373633]
|
||||||
|
- Bump golang.org/x/net in /integration/_fixtures/version_mismatch_fixture (#1286) [6e3cf65]
|
||||||
|
|
||||||
## 2.13.0
|
## 2.13.0
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/onsi/ginkgo/v2/types"
|
"github.com/onsi/ginkgo/v2/types"
|
||||||
|
@ -192,7 +193,7 @@ func precompiledTestSuite(path string) (TestSuite, error) {
|
||||||
return TestSuite{}, errors.New("this is not a .test binary")
|
return TestSuite{}, errors.New("this is not a .test binary")
|
||||||
}
|
}
|
||||||
|
|
||||||
if filepath.Ext(path) == ".test" && info.Mode()&0111 == 0 {
|
if filepath.Ext(path) == ".test" && runtime.GOOS != "windows" && info.Mode()&0111 == 0 {
|
||||||
return TestSuite{}, errors.New("this is not executable")
|
return TestSuite{}, errors.New("this is not executable")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +226,7 @@ func suitesInDir(dir string, recurse bool) TestSuites {
|
||||||
files, _ := os.ReadDir(dir)
|
files, _ := os.ReadDir(dir)
|
||||||
re := regexp.MustCompile(`^[^._].*_test\.go$`)
|
re := regexp.MustCompile(`^[^._].*_test\.go$`)
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
if !file.IsDir() && re.Match([]byte(file.Name())) {
|
if !file.IsDir() && re.MatchString(file.Name()) {
|
||||||
suite := TestSuite{
|
suite := TestSuite{
|
||||||
Path: relPath(dir),
|
Path: relPath(dir),
|
||||||
PackageName: packageNameForSuite(dir),
|
PackageName: packageNameForSuite(dir),
|
||||||
|
@ -240,7 +241,7 @@ func suitesInDir(dir string, recurse bool) TestSuites {
|
||||||
if recurse {
|
if recurse {
|
||||||
re = regexp.MustCompile(`^[._]`)
|
re = regexp.MustCompile(`^[._]`)
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
if file.IsDir() && !re.Match([]byte(file.Name())) {
|
if file.IsDir() && !re.MatchString(file.Name()) {
|
||||||
suites = append(suites, suitesInDir(dir+"/"+file.Name(), recurse)...)
|
suites = append(suites, suitesInDir(dir+"/"+file.Name(), recurse)...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,7 +272,7 @@ func filesHaveGinkgoSuite(dir string, files []os.DirEntry) bool {
|
||||||
reGinkgo := regexp.MustCompile(`package ginkgo|\/ginkgo"|\/ginkgo\/v2"|\/ginkgo\/v2/dsl/`)
|
reGinkgo := regexp.MustCompile(`package ginkgo|\/ginkgo"|\/ginkgo\/v2"|\/ginkgo\/v2/dsl/`)
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
if !file.IsDir() && reTestFile.Match([]byte(file.Name())) {
|
if !file.IsDir() && reTestFile.MatchString(file.Name()) {
|
||||||
contents, _ := os.ReadFile(dir + "/" + file.Name())
|
contents, _ := os.ReadFile(dir + "/" + file.Name())
|
||||||
if reGinkgo.Match(contents) {
|
if reGinkgo.Match(contents) {
|
||||||
return true
|
return true
|
||||||
|
|
|
@ -78,7 +78,7 @@ func (d Dependencies) resolveAndAdd(deps []string, depth int) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !pkg.Goroot && (!ginkgoAndGomegaFilter.Match([]byte(pkg.Dir)) || ginkgoIntegrationTestFilter.Match([]byte(pkg.Dir))) {
|
if !pkg.Goroot && (!ginkgoAndGomegaFilter.MatchString(pkg.Dir) || ginkgoIntegrationTestFilter.MatchString(pkg.Dir)) {
|
||||||
d.addDepIfNotPresent(pkg.Dir, depth)
|
d.addDepIfNotPresent(pkg.Dir, depth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ func (p *PackageHash) computeHashes() (codeHash string, codeModifiedTime time.Ti
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if goTestRegExp.Match([]byte(info.Name())) {
|
if goTestRegExp.MatchString(info.Name()) {
|
||||||
testHash += p.hashForFileInfo(info)
|
testHash += p.hashForFileInfo(info)
|
||||||
if info.ModTime().After(testModifiedTime) {
|
if info.ModTime().After(testModifiedTime) {
|
||||||
testModifiedTime = info.ModTime()
|
testModifiedTime = info.ModTime()
|
||||||
|
@ -87,7 +87,7 @@ func (p *PackageHash) computeHashes() (codeHash string, codeModifiedTime time.Ti
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.watchRegExp.Match([]byte(info.Name())) {
|
if p.watchRegExp.MatchString(info.Name()) {
|
||||||
codeHash += p.hashForFileInfo(info)
|
codeHash += p.hashForFileInfo(info)
|
||||||
if info.ModTime().After(codeModifiedTime) {
|
if info.ModTime().After(codeModifiedTime) {
|
||||||
codeModifiedTime = info.ModTime()
|
codeModifiedTime = info.ModTime()
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
package ginkgo
|
package ginkgo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/onsi/ginkgo/v2/internal/testingtproxy"
|
"github.com/onsi/ginkgo/v2/internal/testingtproxy"
|
||||||
|
"github.com/onsi/ginkgo/v2/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -15,7 +18,7 @@ correct line number associated with the failure - though you do not need to use
|
||||||
You can learn more here: https://onsi.github.io/ginkgo/#using-third-party-libraries
|
You can learn more here: https://onsi.github.io/ginkgo/#using-third-party-libraries
|
||||||
*/
|
*/
|
||||||
func GinkgoT(optionalOffset ...int) FullGinkgoTInterface {
|
func GinkgoT(optionalOffset ...int) FullGinkgoTInterface {
|
||||||
offset := 3
|
offset := 1
|
||||||
if len(optionalOffset) > 0 {
|
if len(optionalOffset) > 0 {
|
||||||
offset = optionalOffset[0]
|
offset = optionalOffset[0]
|
||||||
}
|
}
|
||||||
|
@ -41,21 +44,21 @@ The portion of the interface returned by GinkgoT() that maps onto methods in the
|
||||||
type GinkgoTInterface interface {
|
type GinkgoTInterface interface {
|
||||||
Cleanup(func())
|
Cleanup(func())
|
||||||
Setenv(kev, value string)
|
Setenv(kev, value string)
|
||||||
Error(args ...interface{})
|
Error(args ...any)
|
||||||
Errorf(format string, args ...interface{})
|
Errorf(format string, args ...any)
|
||||||
Fail()
|
Fail()
|
||||||
FailNow()
|
FailNow()
|
||||||
Failed() bool
|
Failed() bool
|
||||||
Fatal(args ...interface{})
|
Fatal(args ...any)
|
||||||
Fatalf(format string, args ...interface{})
|
Fatalf(format string, args ...any)
|
||||||
Helper()
|
Helper()
|
||||||
Log(args ...interface{})
|
Log(args ...any)
|
||||||
Logf(format string, args ...interface{})
|
Logf(format string, args ...any)
|
||||||
Name() string
|
Name() string
|
||||||
Parallel()
|
Parallel()
|
||||||
Skip(args ...interface{})
|
Skip(args ...any)
|
||||||
SkipNow()
|
SkipNow()
|
||||||
Skipf(format string, args ...interface{})
|
Skipf(format string, args ...any)
|
||||||
Skipped() bool
|
Skipped() bool
|
||||||
TempDir() string
|
TempDir() string
|
||||||
}
|
}
|
||||||
|
@ -71,9 +74,9 @@ type FullGinkgoTInterface interface {
|
||||||
AddReportEntryVisibilityNever(name string, args ...any)
|
AddReportEntryVisibilityNever(name string, args ...any)
|
||||||
|
|
||||||
//Prints to the GinkgoWriter
|
//Prints to the GinkgoWriter
|
||||||
Print(a ...interface{})
|
Print(a ...any)
|
||||||
Printf(format string, a ...interface{})
|
Printf(format string, a ...any)
|
||||||
Println(a ...interface{})
|
Println(a ...any)
|
||||||
|
|
||||||
//Provides access to Ginkgo's color formatting, correctly configured to match the color settings specified in the invocation of ginkgo
|
//Provides access to Ginkgo's color formatting, correctly configured to match the color settings specified in the invocation of ginkgo
|
||||||
F(format string, args ...any) string
|
F(format string, args ...any) string
|
||||||
|
@ -92,3 +95,81 @@ type FullGinkgoTInterface interface {
|
||||||
|
|
||||||
AttachProgressReporter(func() string) func()
|
AttachProgressReporter(func() string) func()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
GinkgoTB() implements a wrapper that exactly matches the testing.TB interface.
|
||||||
|
|
||||||
|
In go 1.18 a new private() function was added to the testing.TB interface. Any function which accepts testing.TB as input needs to be passed in something that directly implements testing.TB.
|
||||||
|
|
||||||
|
This wrapper satisfies the testing.TB interface and intended to be used as a drop-in replacement with third party libraries that accept testing.TB.
|
||||||
|
|
||||||
|
Similar to GinkgoT(), GinkgoTB() takes an optional offset argument that can be used to get the
|
||||||
|
correct line number associated with the failure - though you do not need to use this if you call GinkgoHelper() or GinkgoT().Helper() appropriately
|
||||||
|
*/
|
||||||
|
func GinkgoTB(optionalOffset ...int) *GinkgoTBWrapper {
|
||||||
|
offset := 2
|
||||||
|
if len(optionalOffset) > 0 {
|
||||||
|
offset = optionalOffset[0]
|
||||||
|
}
|
||||||
|
return &GinkgoTBWrapper{GinkgoT: GinkgoT(offset)}
|
||||||
|
}
|
||||||
|
|
||||||
|
type GinkgoTBWrapper struct {
|
||||||
|
testing.TB
|
||||||
|
GinkgoT FullGinkgoTInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GinkgoTBWrapper) Cleanup(f func()) {
|
||||||
|
g.GinkgoT.Cleanup(f)
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) Error(args ...any) {
|
||||||
|
g.GinkgoT.Error(args...)
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) Errorf(format string, args ...any) {
|
||||||
|
g.GinkgoT.Errorf(format, args...)
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) Fail() {
|
||||||
|
g.GinkgoT.Fail()
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) FailNow() {
|
||||||
|
g.GinkgoT.FailNow()
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) Failed() bool {
|
||||||
|
return g.GinkgoT.Failed()
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) Fatal(args ...any) {
|
||||||
|
g.GinkgoT.Fatal(args...)
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) Fatalf(format string, args ...any) {
|
||||||
|
g.GinkgoT.Fatalf(format, args...)
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) Helper() {
|
||||||
|
types.MarkAsHelper(1)
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) Log(args ...any) {
|
||||||
|
g.GinkgoT.Log(args...)
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) Logf(format string, args ...any) {
|
||||||
|
g.GinkgoT.Logf(format, args...)
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) Name() string {
|
||||||
|
return g.GinkgoT.Name()
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) Setenv(key, value string) {
|
||||||
|
g.GinkgoT.Setenv(key, value)
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) Skip(args ...any) {
|
||||||
|
g.GinkgoT.Skip(args...)
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) SkipNow() {
|
||||||
|
g.GinkgoT.SkipNow()
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) Skipf(format string, args ...any) {
|
||||||
|
g.GinkgoT.Skipf(format, args...)
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) Skipped() bool {
|
||||||
|
return g.GinkgoT.Skipped()
|
||||||
|
}
|
||||||
|
func (g *GinkgoTBWrapper) TempDir() string {
|
||||||
|
return g.GinkgoT.TempDir()
|
||||||
|
}
|
||||||
|
|
7
vendor/github.com/onsi/ginkgo/v2/internal/output_interceptor_wasm.go
generated
vendored
Normal file
7
vendor/github.com/onsi/ginkgo/v2/internal/output_interceptor_wasm.go
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
//go:build wasm
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
func NewOutputInterceptor() OutputInterceptor {
|
||||||
|
return &NoopOutputInterceptor{}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
//go:build wasm
|
||||||
|
|
||||||
|
package internal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
var PROGRESS_SIGNALS = []os.Signal{syscall.SIGUSR1}
|
|
@ -79,7 +79,7 @@ func NewSuite() *Suite {
|
||||||
|
|
||||||
func (suite *Suite) Clone() (*Suite, error) {
|
func (suite *Suite) Clone() (*Suite, error) {
|
||||||
if suite.phase != PhaseBuildTopLevel {
|
if suite.phase != PhaseBuildTopLevel {
|
||||||
return nil, fmt.Errorf("cnanot clone suite after tree has been built")
|
return nil, fmt.Errorf("cannot clone suite after tree has been built")
|
||||||
}
|
}
|
||||||
return &Suite{
|
return &Suite{
|
||||||
tree: &TreeNode{},
|
tree: &TreeNode{},
|
||||||
|
|
|
@ -18,6 +18,7 @@ func GenerateJSONReport(report types.Report, destination string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
enc := json.NewEncoder(f)
|
enc := json.NewEncoder(f)
|
||||||
enc.SetIndent("", " ")
|
enc.SetIndent("", " ")
|
||||||
err = enc.Encode([]types.Report{
|
err = enc.Encode([]types.Report{
|
||||||
|
@ -26,7 +27,7 @@ func GenerateJSONReport(report types.Report, destination string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return f.Close()
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MergeJSONReports produces a single JSON-formatted report at the passed in destination by merging the JSON-formatted reports provided in sources
|
// MergeJSONReports produces a single JSON-formatted report at the passed in destination by merging the JSON-formatted reports provided in sources
|
||||||
|
@ -57,11 +58,12 @@ func MergeAndCleanupJSONReports(sources []string, destination string) ([]string,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return messages, err
|
return messages, err
|
||||||
}
|
}
|
||||||
|
defer f.Close()
|
||||||
enc := json.NewEncoder(f)
|
enc := json.NewEncoder(f)
|
||||||
enc.SetIndent("", " ")
|
enc.SetIndent("", " ")
|
||||||
err = enc.Encode(allReports)
|
err = enc.Encode(allReports)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return messages, err
|
return messages, err
|
||||||
}
|
}
|
||||||
return messages, f.Close()
|
return messages, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ And can explore some Table patterns here: https://onsi.github.io/ginkgo/#table-s
|
||||||
*/
|
*/
|
||||||
func DescribeTable(description string, args ...interface{}) bool {
|
func DescribeTable(description string, args ...interface{}) bool {
|
||||||
GinkgoHelper()
|
GinkgoHelper()
|
||||||
generateTable(description, args...)
|
generateTable(description, false, args...)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ You can focus a table with `FDescribeTable`. This is equivalent to `FDescribe`.
|
||||||
func FDescribeTable(description string, args ...interface{}) bool {
|
func FDescribeTable(description string, args ...interface{}) bool {
|
||||||
GinkgoHelper()
|
GinkgoHelper()
|
||||||
args = append(args, internal.Focus)
|
args = append(args, internal.Focus)
|
||||||
generateTable(description, args...)
|
generateTable(description, false, args...)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ You can mark a table as pending with `PDescribeTable`. This is equivalent to `P
|
||||||
func PDescribeTable(description string, args ...interface{}) bool {
|
func PDescribeTable(description string, args ...interface{}) bool {
|
||||||
GinkgoHelper()
|
GinkgoHelper()
|
||||||
args = append(args, internal.Pending)
|
args = append(args, internal.Pending)
|
||||||
generateTable(description, args...)
|
generateTable(description, false, args...)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,71 @@ You can mark a table as pending with `XDescribeTable`. This is equivalent to `X
|
||||||
*/
|
*/
|
||||||
var XDescribeTable = PDescribeTable
|
var XDescribeTable = PDescribeTable
|
||||||
|
|
||||||
|
/*
|
||||||
|
DescribeTableSubtree describes a table-driven spec that generates a set of tests for each entry.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
DescribeTableSubtree("a subtree table",
|
||||||
|
func(url string, code int, message string) {
|
||||||
|
var resp *http.Response
|
||||||
|
BeforeEach(func() {
|
||||||
|
var err error
|
||||||
|
resp, err = http.Get(url)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
DeferCleanup(resp.Body.Close)
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should return the expected status code", func() {
|
||||||
|
Expect(resp.StatusCode).To(Equal(code))
|
||||||
|
})
|
||||||
|
|
||||||
|
It("should return the expected message", func() {
|
||||||
|
body, err := ioutil.ReadAll(resp.Body)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(string(body)).To(Equal(message))
|
||||||
|
})
|
||||||
|
},
|
||||||
|
Entry("default response", "example.com/response", http.StatusOK, "hello world"),
|
||||||
|
Entry("missing response", "example.com/missing", http.StatusNotFound, "wat?"),
|
||||||
|
)
|
||||||
|
|
||||||
|
Note that you **must** place define an It inside the body function.
|
||||||
|
|
||||||
|
You can learn more about DescribeTableSubtree here: https://onsi.github.io/ginkgo/#table-specs
|
||||||
|
And can explore some Table patterns here: https://onsi.github.io/ginkgo/#table-specs-patterns
|
||||||
|
*/
|
||||||
|
func DescribeTableSubtree(description string, args ...interface{}) bool {
|
||||||
|
GinkgoHelper()
|
||||||
|
generateTable(description, true, args...)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
You can focus a table with `FDescribeTableSubtree`. This is equivalent to `FDescribe`.
|
||||||
|
*/
|
||||||
|
func FDescribeTableSubtree(description string, args ...interface{}) bool {
|
||||||
|
GinkgoHelper()
|
||||||
|
args = append(args, internal.Focus)
|
||||||
|
generateTable(description, true, args...)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
You can mark a table as pending with `PDescribeTableSubtree`. This is equivalent to `PDescribe`.
|
||||||
|
*/
|
||||||
|
func PDescribeTableSubtree(description string, args ...interface{}) bool {
|
||||||
|
GinkgoHelper()
|
||||||
|
args = append(args, internal.Pending)
|
||||||
|
generateTable(description, true, args...)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
You can mark a table as pending with `XDescribeTableSubtree`. This is equivalent to `XDescribe`.
|
||||||
|
*/
|
||||||
|
var XDescribeTableSubtree = PDescribeTableSubtree
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TableEntry represents an entry in a table test. You generally use the `Entry` constructor.
|
TableEntry represents an entry in a table test. You generally use the `Entry` constructor.
|
||||||
*/
|
*/
|
||||||
|
@ -131,14 +196,14 @@ var XEntry = PEntry
|
||||||
var contextType = reflect.TypeOf(new(context.Context)).Elem()
|
var contextType = reflect.TypeOf(new(context.Context)).Elem()
|
||||||
var specContextType = reflect.TypeOf(new(SpecContext)).Elem()
|
var specContextType = reflect.TypeOf(new(SpecContext)).Elem()
|
||||||
|
|
||||||
func generateTable(description string, args ...interface{}) {
|
func generateTable(description string, isSubtree bool, args ...interface{}) {
|
||||||
GinkgoHelper()
|
GinkgoHelper()
|
||||||
cl := types.NewCodeLocation(0)
|
cl := types.NewCodeLocation(0)
|
||||||
containerNodeArgs := []interface{}{cl}
|
containerNodeArgs := []interface{}{cl}
|
||||||
|
|
||||||
entries := []TableEntry{}
|
entries := []TableEntry{}
|
||||||
var itBody interface{}
|
var internalBody interface{}
|
||||||
var itBodyType reflect.Type
|
var internalBodyType reflect.Type
|
||||||
|
|
||||||
var tableLevelEntryDescription interface{}
|
var tableLevelEntryDescription interface{}
|
||||||
tableLevelEntryDescription = func(args ...interface{}) string {
|
tableLevelEntryDescription = func(args ...interface{}) string {
|
||||||
|
@ -166,11 +231,11 @@ func generateTable(description string, args ...interface{}) {
|
||||||
case t.Kind() == reflect.Func && t.NumOut() == 1 && t.Out(0) == reflect.TypeOf(""):
|
case t.Kind() == reflect.Func && t.NumOut() == 1 && t.Out(0) == reflect.TypeOf(""):
|
||||||
tableLevelEntryDescription = arg
|
tableLevelEntryDescription = arg
|
||||||
case t.Kind() == reflect.Func:
|
case t.Kind() == reflect.Func:
|
||||||
if itBody != nil {
|
if internalBody != nil {
|
||||||
exitIfErr(types.GinkgoErrors.MultipleEntryBodyFunctionsForTable(cl))
|
exitIfErr(types.GinkgoErrors.MultipleEntryBodyFunctionsForTable(cl))
|
||||||
}
|
}
|
||||||
itBody = arg
|
internalBody = arg
|
||||||
itBodyType = reflect.TypeOf(itBody)
|
internalBodyType = reflect.TypeOf(internalBody)
|
||||||
default:
|
default:
|
||||||
containerNodeArgs = append(containerNodeArgs, arg)
|
containerNodeArgs = append(containerNodeArgs, arg)
|
||||||
}
|
}
|
||||||
|
@ -200,39 +265,47 @@ func generateTable(description string, args ...interface{}) {
|
||||||
err = types.GinkgoErrors.InvalidEntryDescription(entry.codeLocation)
|
err = types.GinkgoErrors.InvalidEntryDescription(entry.codeLocation)
|
||||||
}
|
}
|
||||||
|
|
||||||
itNodeArgs := []interface{}{entry.codeLocation}
|
internalNodeArgs := []interface{}{entry.codeLocation}
|
||||||
itNodeArgs = append(itNodeArgs, entry.decorations...)
|
internalNodeArgs = append(internalNodeArgs, entry.decorations...)
|
||||||
|
|
||||||
hasContext := false
|
hasContext := false
|
||||||
if itBodyType.NumIn() > 0. {
|
if internalBodyType.NumIn() > 0. {
|
||||||
if itBodyType.In(0).Implements(specContextType) {
|
if internalBodyType.In(0).Implements(specContextType) {
|
||||||
hasContext = true
|
hasContext = true
|
||||||
} else if itBodyType.In(0).Implements(contextType) && (len(entry.parameters) == 0 || !reflect.TypeOf(entry.parameters[0]).Implements(contextType)) {
|
} else if internalBodyType.In(0).Implements(contextType) && (len(entry.parameters) == 0 || !reflect.TypeOf(entry.parameters[0]).Implements(contextType)) {
|
||||||
hasContext = true
|
hasContext = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = validateParameters(itBody, entry.parameters, "Table Body function", entry.codeLocation, hasContext)
|
err = validateParameters(internalBody, entry.parameters, "Table Body function", entry.codeLocation, hasContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
if hasContext {
|
if hasContext {
|
||||||
itNodeArgs = append(itNodeArgs, func(c SpecContext) {
|
internalNodeArgs = append(internalNodeArgs, func(c SpecContext) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
invokeFunction(itBody, append([]interface{}{c}, entry.parameters...))
|
invokeFunction(internalBody, append([]interface{}{c}, entry.parameters...))
|
||||||
})
|
})
|
||||||
|
if isSubtree {
|
||||||
|
exitIfErr(types.GinkgoErrors.ContextsCannotBeUsedInSubtreeTables(cl))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
itNodeArgs = append(itNodeArgs, func() {
|
internalNodeArgs = append(internalNodeArgs, func() {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
invokeFunction(itBody, entry.parameters)
|
invokeFunction(internalBody, entry.parameters)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pushNode(internal.NewNode(deprecationTracker, types.NodeTypeIt, description, itNodeArgs...))
|
internalNodeType := types.NodeTypeIt
|
||||||
|
if isSubtree {
|
||||||
|
internalNodeType = types.NodeTypeContainer
|
||||||
|
}
|
||||||
|
|
||||||
|
pushNode(internal.NewNode(deprecationTracker, internalNodeType, description, internalNodeArgs...))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -149,7 +149,7 @@ func PruneStack(fullStackTrace string, skip int) string {
|
||||||
re := regexp.MustCompile(`\/ginkgo\/|\/pkg\/testing\/|\/pkg\/runtime\/`)
|
re := regexp.MustCompile(`\/ginkgo\/|\/pkg\/testing\/|\/pkg\/runtime\/`)
|
||||||
for i := 0; i < len(stack)/2; i++ {
|
for i := 0; i < len(stack)/2; i++ {
|
||||||
// We filter out based on the source code file name.
|
// We filter out based on the source code file name.
|
||||||
if !re.Match([]byte(stack[i*2+1])) {
|
if !re.MatchString(stack[i*2+1]) {
|
||||||
prunedStack = append(prunedStack, stack[i*2])
|
prunedStack = append(prunedStack, stack[i*2])
|
||||||
prunedStack = append(prunedStack, stack[i*2+1])
|
prunedStack = append(prunedStack, stack[i*2+1])
|
||||||
}
|
}
|
||||||
|
|
|
@ -505,6 +505,15 @@ func (g ginkgoErrors) IncorrectVariadicParameterTypeToTableFunction(expected, ac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (g ginkgoErrors) ContextsCannotBeUsedInSubtreeTables(cl CodeLocation) error {
|
||||||
|
return GinkgoError{
|
||||||
|
Heading: "Contexts cannot be used in subtree tables",
|
||||||
|
Message: "You''ve defined a subtree body function that accepts a context but did not provide one in the table entry. Ginkgo SpecContexts can only be passed in to subject and setup nodes - so if you are trying to implement a spec timeout you should request a context in the It function within your subtree body function, not in the subtree body function itself.",
|
||||||
|
CodeLocation: cl,
|
||||||
|
DocLink: "table-specs",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Parallel Synchronization errors */
|
/* Parallel Synchronization errors */
|
||||||
|
|
||||||
func (g ginkgoErrors) AggregatedReportUnavailableDueToNodeDisappearing() error {
|
func (g ginkgoErrors) AggregatedReportUnavailableDueToNodeDisappearing() error {
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
const VERSION = "2.13.0"
|
const VERSION = "2.14.0"
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
## 1.30.0
|
||||||
|
|
||||||
|
### Features
|
||||||
|
- BeTrueBecause and BeFalseBecause allow for better failure messages [4da4c7f]
|
||||||
|
|
||||||
|
### Maintenance
|
||||||
|
- Bump actions/checkout from 3 to 4 (#694) [6ca6e97]
|
||||||
|
- doc: fix type on gleak go doc [f1b8343]
|
||||||
|
|
||||||
## 1.29.0
|
## 1.29.0
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
"github.com/onsi/gomega/types"
|
"github.com/onsi/gomega/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
const GOMEGA_VERSION = "1.29.0"
|
const GOMEGA_VERSION = "1.30.0"
|
||||||
|
|
||||||
const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler.
|
const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler.
|
||||||
If you're using Ginkgo then you probably forgot to put your assertion in an It().
|
If you're using Ginkgo then you probably forgot to put your assertion in an It().
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package gomega
|
package gomega
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
@ -52,15 +53,31 @@ func BeNil() types.GomegaMatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
// BeTrue succeeds if actual is true
|
// BeTrue succeeds if actual is true
|
||||||
|
//
|
||||||
|
// In general, it's better to use `BeTrueBecause(reason)` to provide a more useful error message if a true check fails.
|
||||||
func BeTrue() types.GomegaMatcher {
|
func BeTrue() types.GomegaMatcher {
|
||||||
return &matchers.BeTrueMatcher{}
|
return &matchers.BeTrueMatcher{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// BeFalse succeeds if actual is false
|
// BeFalse succeeds if actual is false
|
||||||
|
//
|
||||||
|
// In general, it's better to use `BeFalseBecause(reason)` to provide a more useful error message if a false check fails.
|
||||||
func BeFalse() types.GomegaMatcher {
|
func BeFalse() types.GomegaMatcher {
|
||||||
return &matchers.BeFalseMatcher{}
|
return &matchers.BeFalseMatcher{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BeTrueBecause succeeds if actual is true and displays the provided reason if it is false
|
||||||
|
// fmt.Sprintf is used to render the reason
|
||||||
|
func BeTrueBecause(format string, args ...any) types.GomegaMatcher {
|
||||||
|
return &matchers.BeTrueMatcher{Reason: fmt.Sprintf(format, args...)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BeFalseBecause succeeds if actual is false and displays the provided reason if it is true.
|
||||||
|
// fmt.Sprintf is used to render the reason
|
||||||
|
func BeFalseBecause(format string, args ...any) types.GomegaMatcher {
|
||||||
|
return &matchers.BeFalseMatcher{Reason: fmt.Sprintf(format, args...)}
|
||||||
|
}
|
||||||
|
|
||||||
// HaveOccurred succeeds if actual is a non-nil error
|
// HaveOccurred succeeds if actual is a non-nil error
|
||||||
// The typical Go error checking pattern looks like:
|
// The typical Go error checking pattern looks like:
|
||||||
//
|
//
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type BeFalseMatcher struct {
|
type BeFalseMatcher struct {
|
||||||
|
Reason string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (matcher *BeFalseMatcher) Match(actual interface{}) (success bool, err error) {
|
func (matcher *BeFalseMatcher) Match(actual interface{}) (success bool, err error) {
|
||||||
|
@ -20,9 +21,17 @@ func (matcher *BeFalseMatcher) Match(actual interface{}) (success bool, err erro
|
||||||
}
|
}
|
||||||
|
|
||||||
func (matcher *BeFalseMatcher) FailureMessage(actual interface{}) (message string) {
|
func (matcher *BeFalseMatcher) FailureMessage(actual interface{}) (message string) {
|
||||||
return format.Message(actual, "to be false")
|
if matcher.Reason == "" {
|
||||||
|
return format.Message(actual, "to be false")
|
||||||
|
} else {
|
||||||
|
return matcher.Reason
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (matcher *BeFalseMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
func (matcher *BeFalseMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||||
return format.Message(actual, "not to be false")
|
if matcher.Reason == "" {
|
||||||
|
return format.Message(actual, "not to be false")
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf(`Expected not false but got false\nNegation of "%s" failed`, matcher.Reason)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type BeTrueMatcher struct {
|
type BeTrueMatcher struct {
|
||||||
|
Reason string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (matcher *BeTrueMatcher) Match(actual interface{}) (success bool, err error) {
|
func (matcher *BeTrueMatcher) Match(actual interface{}) (success bool, err error) {
|
||||||
|
@ -20,9 +21,17 @@ func (matcher *BeTrueMatcher) Match(actual interface{}) (success bool, err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (matcher *BeTrueMatcher) FailureMessage(actual interface{}) (message string) {
|
func (matcher *BeTrueMatcher) FailureMessage(actual interface{}) (message string) {
|
||||||
return format.Message(actual, "to be true")
|
if matcher.Reason == "" {
|
||||||
|
return format.Message(actual, "to be true")
|
||||||
|
} else {
|
||||||
|
return matcher.Reason
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (matcher *BeTrueMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
func (matcher *BeTrueMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||||
return format.Message(actual, "not to be true")
|
if matcher.Reason == "" {
|
||||||
|
return format.Message(actual, "not to be true")
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf(`Expected not true but got true\nNegation of "%s" failed`, matcher.Reason)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
package expfmt
|
package expfmt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
@ -21,8 +22,8 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
"google.golang.org/protobuf/encoding/protodelim"
|
||||||
|
|
||||||
"github.com/matttproud/golang_protobuf_extensions/v2/pbutil"
|
|
||||||
"github.com/prometheus/common/model"
|
"github.com/prometheus/common/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -86,8 +87,10 @@ type protoDecoder struct {
|
||||||
|
|
||||||
// Decode implements the Decoder interface.
|
// Decode implements the Decoder interface.
|
||||||
func (d *protoDecoder) Decode(v *dto.MetricFamily) error {
|
func (d *protoDecoder) Decode(v *dto.MetricFamily) error {
|
||||||
_, err := pbutil.ReadDelimited(d.r, v)
|
opts := protodelim.UnmarshalOptions{
|
||||||
if err != nil {
|
MaxSize: -1,
|
||||||
|
}
|
||||||
|
if err := opts.UnmarshalFrom(bufio.NewReader(d.r), v); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !model.IsValidMetricName(model.LabelValue(v.GetName())) {
|
if !model.IsValidMetricName(model.LabelValue(v.GetName())) {
|
||||||
|
|
|
@ -18,10 +18,11 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/matttproud/golang_protobuf_extensions/v2/pbutil"
|
"google.golang.org/protobuf/encoding/protodelim"
|
||||||
"github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg"
|
|
||||||
"google.golang.org/protobuf/encoding/prototext"
|
"google.golang.org/protobuf/encoding/prototext"
|
||||||
|
|
||||||
|
"github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg"
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -120,7 +121,7 @@ func NewEncoder(w io.Writer, format Format) Encoder {
|
||||||
case FmtProtoDelim:
|
case FmtProtoDelim:
|
||||||
return encoderCloser{
|
return encoderCloser{
|
||||||
encode: func(v *dto.MetricFamily) error {
|
encode: func(v *dto.MetricFamily) error {
|
||||||
_, err := pbutil.WriteDelimited(w, v)
|
_, err := protodelim.MarshalTo(w, v)
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
close: func() error { return nil },
|
close: func() error { return nil },
|
||||||
|
|
|
@ -16,6 +16,7 @@ package expfmt
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
|
@ -24,8 +25,9 @@ import (
|
||||||
|
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
|
|
||||||
"github.com/prometheus/common/model"
|
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
|
|
||||||
|
"github.com/prometheus/common/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A stateFn is a function that represents a state in a state machine. By
|
// A stateFn is a function that represents a state in a state machine. By
|
||||||
|
@ -112,7 +114,7 @@ func (p *TextParser) TextToMetricFamilies(in io.Reader) (map[string]*dto.MetricF
|
||||||
// stream. Turn this error into something nicer and more
|
// stream. Turn this error into something nicer and more
|
||||||
// meaningful. (io.EOF is often used as a signal for the legitimate end
|
// meaningful. (io.EOF is often used as a signal for the legitimate end
|
||||||
// of an input stream.)
|
// of an input stream.)
|
||||||
if p.err == io.EOF {
|
if p.err != nil && errors.Is(p.err, io.EOF) {
|
||||||
p.parseError("unexpected end of input stream")
|
p.parseError("unexpected end of input stream")
|
||||||
}
|
}
|
||||||
return p.metricFamiliesByName, p.err
|
return p.metricFamiliesByName, p.err
|
||||||
|
@ -146,7 +148,7 @@ func (p *TextParser) startOfLine() stateFn {
|
||||||
// which is not an error but the signal that we are done.
|
// which is not an error but the signal that we are done.
|
||||||
// Any other error that happens to align with the start of
|
// Any other error that happens to align with the start of
|
||||||
// a line is still an error.
|
// a line is still an error.
|
||||||
if p.err == io.EOF {
|
if errors.Is(p.err, io.EOF) {
|
||||||
p.err = nil
|
p.err = nil
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -90,13 +90,13 @@ func (a *Alert) Validate() error {
|
||||||
return fmt.Errorf("start time must be before end time")
|
return fmt.Errorf("start time must be before end time")
|
||||||
}
|
}
|
||||||
if err := a.Labels.Validate(); err != nil {
|
if err := a.Labels.Validate(); err != nil {
|
||||||
return fmt.Errorf("invalid label set: %s", err)
|
return fmt.Errorf("invalid label set: %w", err)
|
||||||
}
|
}
|
||||||
if len(a.Labels) == 0 {
|
if len(a.Labels) == 0 {
|
||||||
return fmt.Errorf("at least one label pair required")
|
return fmt.Errorf("at least one label pair required")
|
||||||
}
|
}
|
||||||
if err := a.Annotations.Validate(); err != nil {
|
if err := a.Annotations.Validate(); err != nil {
|
||||||
return fmt.Errorf("invalid annotations: %s", err)
|
return fmt.Errorf("invalid annotations: %w", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
// 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 model
|
||||||
|
|
||||||
|
// MetricType represents metric type values.
|
||||||
|
type MetricType string
|
||||||
|
|
||||||
|
const (
|
||||||
|
MetricTypeCounter = MetricType("counter")
|
||||||
|
MetricTypeGauge = MetricType("gauge")
|
||||||
|
MetricTypeHistogram = MetricType("histogram")
|
||||||
|
MetricTypeGaugeHistogram = MetricType("gaugehistogram")
|
||||||
|
MetricTypeSummary = MetricType("summary")
|
||||||
|
MetricTypeInfo = MetricType("info")
|
||||||
|
MetricTypeStateset = MetricType("stateset")
|
||||||
|
MetricTypeUnknown = MetricType("unknown")
|
||||||
|
)
|
|
@ -20,12 +20,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// MetricNameRE is a regular expression matching valid metric
|
||||||
// MetricNameRE is a regular expression matching valid metric
|
// names. Note that the IsValidMetricName function performs the same
|
||||||
// names. Note that the IsValidMetricName function performs the same
|
// check but faster than a match with this regular expression.
|
||||||
// check but faster than a match with this regular expression.
|
var MetricNameRE = regexp.MustCompile(`^[a-zA-Z_:][a-zA-Z0-9_:]*$`)
|
||||||
MetricNameRE = regexp.MustCompile(`^[a-zA-Z_:][a-zA-Z0-9_:]*$`)
|
|
||||||
)
|
|
||||||
|
|
||||||
// A Metric is similar to a LabelSet, but the key difference is that a Metric is
|
// A Metric is similar to a LabelSet, but the key difference is that a Metric is
|
||||||
// a singleton and refers to one and only one stream of samples.
|
// a singleton and refers to one and only one stream of samples.
|
||||||
|
|
|
@ -22,10 +22,8 @@ import (
|
||||||
// when calculating their combined hash value (aka signature aka fingerprint).
|
// when calculating their combined hash value (aka signature aka fingerprint).
|
||||||
const SeparatorByte byte = 255
|
const SeparatorByte byte = 255
|
||||||
|
|
||||||
var (
|
// cache the signature of an empty label set.
|
||||||
// cache the signature of an empty label set.
|
var emptyLabelSignature = hashNew()
|
||||||
emptyLabelSignature = hashNew()
|
|
||||||
)
|
|
||||||
|
|
||||||
// LabelsToSignature returns a quasi-unique signature (i.e., fingerprint) for a
|
// LabelsToSignature returns a quasi-unique signature (i.e., fingerprint) for a
|
||||||
// given label set. (Collisions are possible but unlikely if the number of label
|
// given label set. (Collisions are possible but unlikely if the number of label
|
||||||
|
|
|
@ -81,7 +81,7 @@ func (s *Silence) Validate() error {
|
||||||
}
|
}
|
||||||
for _, m := range s.Matchers {
|
for _, m := range s.Matchers {
|
||||||
if err := m.Validate(); err != nil {
|
if err := m.Validate(); err != nil {
|
||||||
return fmt.Errorf("invalid matcher: %s", err)
|
return fmt.Errorf("invalid matcher: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.StartsAt.IsZero() {
|
if s.StartsAt.IsZero() {
|
||||||
|
|
|
@ -21,14 +21,12 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// ZeroSample is the pseudo zero-value of Sample used to signal a
|
||||||
// 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,
|
||||||
// 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
|
||||||
// and metric nil. Note that the natural zero value of Sample has a timestamp
|
// of 0, which is possible to appear in a real Sample and thus not suitable
|
||||||
// of 0, which is possible to appear in a real Sample and thus not suitable
|
// to signal a non-existing Sample.
|
||||||
// to signal a non-existing Sample.
|
var ZeroSample = Sample{Timestamp: Earliest}
|
||||||
ZeroSample = Sample{Timestamp: Earliest}
|
|
||||||
)
|
|
||||||
|
|
||||||
// Sample is a sample pair associated with a metric. A single sample must either
|
// 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
|
// define Value or Histogram but not both. Histogram == nil implies the Value
|
||||||
|
@ -274,7 +272,7 @@ func (s *Scalar) UnmarshalJSON(b []byte) error {
|
||||||
|
|
||||||
value, err := strconv.ParseFloat(f, 64)
|
value, err := strconv.ParseFloat(f, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error parsing sample value: %s", err)
|
return fmt.Errorf("error parsing sample value: %w", err)
|
||||||
}
|
}
|
||||||
s.Value = SampleValue(value)
|
s.Value = SampleValue(value)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -20,14 +20,12 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
// ZeroSamplePair is the pseudo zero-value of SamplePair used to signal a
|
||||||
// ZeroSamplePair is the pseudo zero-value of SamplePair used to signal a
|
// non-existing sample pair. It is a SamplePair with timestamp Earliest and
|
||||||
// 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
|
||||||
// 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
|
||||||
// of 0, which is possible to appear in a real SamplePair and thus not
|
// suitable to signal a non-existing SamplePair.
|
||||||
// suitable to signal a non-existing SamplePair.
|
var ZeroSamplePair = SamplePair{Timestamp: Earliest}
|
||||||
ZeroSamplePair = SamplePair{Timestamp: Earliest}
|
|
||||||
)
|
|
||||||
|
|
||||||
// A SampleValue is a representation of a value for a given sample at a given
|
// A SampleValue is a representation of a value for a given sample at a given
|
||||||
// time.
|
// time.
|
||||||
|
|
|
@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [1.11.0] - 2023-05-02
|
||||||
|
### Fixed
|
||||||
|
- Fix initialization of `Value` wrappers.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Add `String` method to `atomic.Pointer[T]` type allowing users to safely print
|
||||||
|
underlying values of pointers.
|
||||||
|
|
||||||
|
[1.11.0]: https://github.com/uber-go/atomic/compare/v1.10.0...v1.11.0
|
||||||
|
|
||||||
## [1.10.0] - 2022-08-11
|
## [1.10.0] - 2022-08-11
|
||||||
### Added
|
### Added
|
||||||
- Add `atomic.Float32` type for atomic operations on `float32`.
|
- Add `atomic.Float32` type for atomic operations on `float32`.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @generated Code generated by gen-atomicwrapper.
|
// @generated Code generated by gen-atomicwrapper.
|
||||||
|
|
||||||
// Copyright (c) 2020-2022 Uber Technologies, Inc.
|
// Copyright (c) 2020-2023 Uber Technologies, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @generated Code generated by gen-atomicwrapper.
|
// @generated Code generated by gen-atomicwrapper.
|
||||||
|
|
||||||
// Copyright (c) 2020-2022 Uber Technologies, Inc.
|
// Copyright (c) 2020-2023 Uber Technologies, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @generated Code generated by gen-atomicwrapper.
|
// @generated Code generated by gen-atomicwrapper.
|
||||||
|
|
||||||
// Copyright (c) 2020-2022 Uber Technologies, Inc.
|
// Copyright (c) 2020-2023 Uber Technologies, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -52,7 +52,17 @@ func (x *Error) Store(val error) {
|
||||||
|
|
||||||
// CompareAndSwap is an atomic compare-and-swap for error values.
|
// CompareAndSwap is an atomic compare-and-swap for error values.
|
||||||
func (x *Error) CompareAndSwap(old, new error) (swapped bool) {
|
func (x *Error) CompareAndSwap(old, new error) (swapped bool) {
|
||||||
return x.v.CompareAndSwap(packError(old), packError(new))
|
if x.v.CompareAndSwap(packError(old), packError(new)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if old == _zeroError {
|
||||||
|
// If the old value is the empty value, then it's possible the
|
||||||
|
// underlying Value hasn't been set and is nil, so retry with nil.
|
||||||
|
return x.v.CompareAndSwap(nil, packError(new))
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap atomically stores the given error and returns the old
|
// Swap atomically stores the given error and returns the old
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @generated Code generated by gen-atomicwrapper.
|
// @generated Code generated by gen-atomicwrapper.
|
||||||
|
|
||||||
// Copyright (c) 2020-2022 Uber Technologies, Inc.
|
// Copyright (c) 2020-2023 Uber Technologies, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @generated Code generated by gen-atomicwrapper.
|
// @generated Code generated by gen-atomicwrapper.
|
||||||
|
|
||||||
// Copyright (c) 2020-2022 Uber Technologies, Inc.
|
// Copyright (c) 2020-2023 Uber Technologies, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @generated Code generated by gen-atomicint.
|
// @generated Code generated by gen-atomicint.
|
||||||
|
|
||||||
// Copyright (c) 2020-2022 Uber Technologies, Inc.
|
// Copyright (c) 2020-2023 Uber Technologies, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @generated Code generated by gen-atomicint.
|
// @generated Code generated by gen-atomicint.
|
||||||
|
|
||||||
// Copyright (c) 2020-2022 Uber Technologies, Inc.
|
// Copyright (c) 2020-2023 Uber Technologies, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -18,43 +18,14 @@
|
||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
//go:build go1.18 && !go1.19
|
//go:build go1.18
|
||||||
// +build go1.18,!go1.19
|
// +build go1.18
|
||||||
|
|
||||||
package atomic
|
package atomic
|
||||||
|
|
||||||
import "unsafe"
|
import "fmt"
|
||||||
|
|
||||||
type Pointer[T any] struct {
|
// String returns a human readable representation of a Pointer's underlying value.
|
||||||
_ nocmp // disallow non-atomic comparison
|
func (p *Pointer[T]) String() string {
|
||||||
p UnsafePointer
|
return fmt.Sprint(p.Load())
|
||||||
}
|
|
||||||
|
|
||||||
// NewPointer creates a new Pointer.
|
|
||||||
func NewPointer[T any](v *T) *Pointer[T] {
|
|
||||||
var p Pointer[T]
|
|
||||||
if v != nil {
|
|
||||||
p.p.Store(unsafe.Pointer(v))
|
|
||||||
}
|
|
||||||
return &p
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load atomically loads the wrapped value.
|
|
||||||
func (p *Pointer[T]) Load() *T {
|
|
||||||
return (*T)(p.p.Load())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store atomically stores the passed value.
|
|
||||||
func (p *Pointer[T]) Store(val *T) {
|
|
||||||
p.p.Store(unsafe.Pointer(val))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap atomically swaps the wrapped pointer and returns the old value.
|
|
||||||
func (p *Pointer[T]) Swap(val *T) (old *T) {
|
|
||||||
return (*T)(p.p.Swap(unsafe.Pointer(val)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// CompareAndSwap is an atomic compare-and-swap.
|
|
||||||
func (p *Pointer[T]) CompareAndSwap(old, new *T) (swapped bool) {
|
|
||||||
return p.p.CompareAndSwap(unsafe.Pointer(old), unsafe.Pointer(new))
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
// Copyright (c) 2022 Uber Technologies, Inc.
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
//go:build go1.18 && !go1.19
|
||||||
|
// +build go1.18,!go1.19
|
||||||
|
|
||||||
|
package atomic
|
||||||
|
|
||||||
|
import "unsafe"
|
||||||
|
|
||||||
|
type Pointer[T any] struct {
|
||||||
|
_ nocmp // disallow non-atomic comparison
|
||||||
|
p UnsafePointer
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPointer creates a new Pointer.
|
||||||
|
func NewPointer[T any](v *T) *Pointer[T] {
|
||||||
|
var p Pointer[T]
|
||||||
|
if v != nil {
|
||||||
|
p.p.Store(unsafe.Pointer(v))
|
||||||
|
}
|
||||||
|
return &p
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load atomically loads the wrapped value.
|
||||||
|
func (p *Pointer[T]) Load() *T {
|
||||||
|
return (*T)(p.p.Load())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store atomically stores the passed value.
|
||||||
|
func (p *Pointer[T]) Store(val *T) {
|
||||||
|
p.p.Store(unsafe.Pointer(val))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swap atomically swaps the wrapped pointer and returns the old value.
|
||||||
|
func (p *Pointer[T]) Swap(val *T) (old *T) {
|
||||||
|
return (*T)(p.p.Swap(unsafe.Pointer(val)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompareAndSwap is an atomic compare-and-swap.
|
||||||
|
func (p *Pointer[T]) CompareAndSwap(old, new *T) (swapped bool) {
|
||||||
|
return p.p.CompareAndSwap(unsafe.Pointer(old), unsafe.Pointer(new))
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
// @generated Code generated by gen-atomicwrapper.
|
// @generated Code generated by gen-atomicwrapper.
|
||||||
|
|
||||||
// Copyright (c) 2020-2022 Uber Technologies, Inc.
|
// Copyright (c) 2020-2023 Uber Technologies, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -42,24 +42,31 @@ func NewString(val string) *String {
|
||||||
|
|
||||||
// Load atomically loads the wrapped string.
|
// Load atomically loads the wrapped string.
|
||||||
func (x *String) Load() string {
|
func (x *String) Load() string {
|
||||||
if v := x.v.Load(); v != nil {
|
return unpackString(x.v.Load())
|
||||||
return v.(string)
|
|
||||||
}
|
|
||||||
return _zeroString
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store atomically stores the passed string.
|
// Store atomically stores the passed string.
|
||||||
func (x *String) Store(val string) {
|
func (x *String) Store(val string) {
|
||||||
x.v.Store(val)
|
x.v.Store(packString(val))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompareAndSwap is an atomic compare-and-swap for string values.
|
// CompareAndSwap is an atomic compare-and-swap for string values.
|
||||||
func (x *String) CompareAndSwap(old, new string) (swapped bool) {
|
func (x *String) CompareAndSwap(old, new string) (swapped bool) {
|
||||||
return x.v.CompareAndSwap(old, new)
|
if x.v.CompareAndSwap(packString(old), packString(new)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if old == _zeroString {
|
||||||
|
// If the old value is the empty value, then it's possible the
|
||||||
|
// underlying Value hasn't been set and is nil, so retry with nil.
|
||||||
|
return x.v.CompareAndSwap(nil, packString(new))
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Swap atomically stores the given string and returns the old
|
// Swap atomically stores the given string and returns the old
|
||||||
// value.
|
// value.
|
||||||
func (x *String) Swap(val string) (old string) {
|
func (x *String) Swap(val string) (old string) {
|
||||||
return x.v.Swap(val).(string)
|
return unpackString(x.v.Swap(packString(val)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright (c) 2020-2022 Uber Technologies, Inc.
|
// Copyright (c) 2020-2023 Uber Technologies, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -20,7 +20,18 @@
|
||||||
|
|
||||||
package atomic
|
package atomic
|
||||||
|
|
||||||
//go:generate bin/gen-atomicwrapper -name=String -type=string -wrapped=Value -compareandswap -swap -file=string.go
|
//go:generate bin/gen-atomicwrapper -name=String -type=string -wrapped Value -pack packString -unpack unpackString -compareandswap -swap -file=string.go
|
||||||
|
|
||||||
|
func packString(s string) interface{} {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func unpackString(v interface{}) string {
|
||||||
|
if s, ok := v.(string); ok {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
// String returns the wrapped value.
|
// String returns the wrapped value.
|
||||||
func (s *String) String() string {
|
func (s *String) String() string {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @generated Code generated by gen-atomicwrapper.
|
// @generated Code generated by gen-atomicwrapper.
|
||||||
|
|
||||||
// Copyright (c) 2020-2022 Uber Technologies, Inc.
|
// Copyright (c) 2020-2023 Uber Technologies, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @generated Code generated by gen-atomicint.
|
// @generated Code generated by gen-atomicint.
|
||||||
|
|
||||||
// Copyright (c) 2020-2022 Uber Technologies, Inc.
|
// Copyright (c) 2020-2023 Uber Technologies, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @generated Code generated by gen-atomicint.
|
// @generated Code generated by gen-atomicint.
|
||||||
|
|
||||||
// Copyright (c) 2020-2022 Uber Technologies, Inc.
|
// Copyright (c) 2020-2023 Uber Technologies, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// @generated Code generated by gen-atomicint.
|
// @generated Code generated by gen-atomicint.
|
||||||
|
|
||||||
// Copyright (c) 2020-2022 Uber Technologies, Inc.
|
// Copyright (c) 2020-2023 Uber Technologies, Inc.
|
||||||
//
|
//
|
||||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
160
vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go
generated
vendored
Normal file
160
vendor/google.golang.org/protobuf/encoding/protodelim/protodelim.go
generated
vendored
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package protodelim marshals and unmarshals varint size-delimited messages.
|
||||||
|
package protodelim
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"google.golang.org/protobuf/encoding/protowire"
|
||||||
|
"google.golang.org/protobuf/internal/errors"
|
||||||
|
"google.golang.org/protobuf/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MarshalOptions is a configurable varint size-delimited marshaler.
|
||||||
|
type MarshalOptions struct{ proto.MarshalOptions }
|
||||||
|
|
||||||
|
// MarshalTo writes a varint size-delimited wire-format message to w.
|
||||||
|
// If w returns an error, MarshalTo returns it unchanged.
|
||||||
|
func (o MarshalOptions) MarshalTo(w io.Writer, m proto.Message) (int, error) {
|
||||||
|
msgBytes, err := o.MarshalOptions.Marshal(m)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sizeBytes := protowire.AppendVarint(nil, uint64(len(msgBytes)))
|
||||||
|
sizeWritten, err := w.Write(sizeBytes)
|
||||||
|
if err != nil {
|
||||||
|
return sizeWritten, err
|
||||||
|
}
|
||||||
|
msgWritten, err := w.Write(msgBytes)
|
||||||
|
if err != nil {
|
||||||
|
return sizeWritten + msgWritten, err
|
||||||
|
}
|
||||||
|
return sizeWritten + msgWritten, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalTo writes a varint size-delimited wire-format message to w
|
||||||
|
// with the default options.
|
||||||
|
//
|
||||||
|
// See the documentation for [MarshalOptions.MarshalTo].
|
||||||
|
func MarshalTo(w io.Writer, m proto.Message) (int, error) {
|
||||||
|
return MarshalOptions{}.MarshalTo(w, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalOptions is a configurable varint size-delimited unmarshaler.
|
||||||
|
type UnmarshalOptions struct {
|
||||||
|
proto.UnmarshalOptions
|
||||||
|
|
||||||
|
// MaxSize is the maximum size in wire-format bytes of a single message.
|
||||||
|
// Unmarshaling a message larger than MaxSize will return an error.
|
||||||
|
// A zero MaxSize will default to 4 MiB.
|
||||||
|
// Setting MaxSize to -1 disables the limit.
|
||||||
|
MaxSize int64
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultMaxSize = 4 << 20 // 4 MiB, corresponds to the default gRPC max request/response size
|
||||||
|
|
||||||
|
// SizeTooLargeError is an error that is returned when the unmarshaler encounters a message size
|
||||||
|
// that is larger than its configured [UnmarshalOptions.MaxSize].
|
||||||
|
type SizeTooLargeError struct {
|
||||||
|
// Size is the varint size of the message encountered
|
||||||
|
// that was larger than the provided MaxSize.
|
||||||
|
Size uint64
|
||||||
|
|
||||||
|
// MaxSize is the MaxSize limit configured in UnmarshalOptions, which Size exceeded.
|
||||||
|
MaxSize uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *SizeTooLargeError) Error() string {
|
||||||
|
return fmt.Sprintf("message size %d exceeded unmarshaler's maximum configured size %d", e.Size, e.MaxSize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reader is the interface expected by [UnmarshalFrom].
|
||||||
|
// It is implemented by *[bufio.Reader].
|
||||||
|
type Reader interface {
|
||||||
|
io.Reader
|
||||||
|
io.ByteReader
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalFrom parses and consumes a varint size-delimited wire-format message
|
||||||
|
// from r.
|
||||||
|
// The provided message must be mutable (e.g., a non-nil pointer to a message).
|
||||||
|
//
|
||||||
|
// The error is [io.EOF] error only if no bytes are read.
|
||||||
|
// If an EOF happens after reading some but not all the bytes,
|
||||||
|
// UnmarshalFrom returns a non-io.EOF error.
|
||||||
|
// In particular if r returns a non-io.EOF error, UnmarshalFrom returns it unchanged,
|
||||||
|
// and if only a size is read with no subsequent message, [io.ErrUnexpectedEOF] is returned.
|
||||||
|
func (o UnmarshalOptions) UnmarshalFrom(r Reader, m proto.Message) error {
|
||||||
|
var sizeArr [binary.MaxVarintLen64]byte
|
||||||
|
sizeBuf := sizeArr[:0]
|
||||||
|
for i := range sizeArr {
|
||||||
|
b, err := r.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
// Immediate EOF is unexpected.
|
||||||
|
if err == io.EOF && i != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sizeBuf = append(sizeBuf, b)
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size, n := protowire.ConsumeVarint(sizeBuf)
|
||||||
|
if n < 0 {
|
||||||
|
return protowire.ParseError(n)
|
||||||
|
}
|
||||||
|
|
||||||
|
maxSize := o.MaxSize
|
||||||
|
if maxSize == 0 {
|
||||||
|
maxSize = defaultMaxSize
|
||||||
|
}
|
||||||
|
if maxSize != -1 && size > uint64(maxSize) {
|
||||||
|
return errors.Wrap(&SizeTooLargeError{Size: size, MaxSize: uint64(maxSize)}, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
var b []byte
|
||||||
|
var err error
|
||||||
|
if br, ok := r.(*bufio.Reader); ok {
|
||||||
|
// Use the []byte from the bufio.Reader instead of having to allocate one.
|
||||||
|
// This reduces CPU usage and allocated bytes.
|
||||||
|
b, err = br.Peek(int(size))
|
||||||
|
if err == nil {
|
||||||
|
defer br.Discard(int(size))
|
||||||
|
} else {
|
||||||
|
b = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if b == nil {
|
||||||
|
b = make([]byte, size)
|
||||||
|
_, err = io.ReadFull(r, b)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == io.EOF {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := o.Unmarshal(b, m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalFrom parses and consumes a varint size-delimited wire-format message
|
||||||
|
// from r with the default options.
|
||||||
|
// The provided message must be mutable (e.g., a non-nil pointer to a message).
|
||||||
|
//
|
||||||
|
// See the documentation for [UnmarshalOptions.UnmarshalFrom].
|
||||||
|
func UnmarshalFrom(r Reader, m proto.Message) error {
|
||||||
|
return UnmarshalOptions{}.UnmarshalFrom(r, m)
|
||||||
|
}
|
|
@ -1,14 +1,16 @@
|
||||||
# See the OWNERS docs at https://go.k8s.io/owners
|
# See the OWNERS docs at https://go.k8s.io/owners
|
||||||
reviewers:
|
reviewers:
|
||||||
- harshanarayana
|
- harshanarayana
|
||||||
|
- mengjiao-liu
|
||||||
- pohly
|
- pohly
|
||||||
approvers:
|
approvers:
|
||||||
- dims
|
- dims
|
||||||
|
- pohly
|
||||||
- thockin
|
- thockin
|
||||||
- serathius
|
|
||||||
emeritus_approvers:
|
emeritus_approvers:
|
||||||
- brancz
|
- brancz
|
||||||
- justinsb
|
- justinsb
|
||||||
- lavalamp
|
- lavalamp
|
||||||
- piosz
|
- piosz
|
||||||
|
- serathius
|
||||||
- tallclair
|
- tallclair
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
//go:build go1.21
|
||||||
|
// +build go1.21
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2021 The Kubernetes 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 klog
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetSlogLogger reconfigures klog to log through the slog logger. The logger must not be nil.
|
||||||
|
func SetSlogLogger(logger *slog.Logger) {
|
||||||
|
SetLoggerWithOptions(logr.FromSlogHandler(logger.Handler()), ContextualLogger(true))
|
||||||
|
}
|
|
@ -14,9 +14,26 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// Package klog implements logging analogous to the Google-internal C++ INFO/ERROR/V setup.
|
// Package klog contains the following functionality:
|
||||||
// It provides functions Info, Warning, Error, Fatal, plus formatting variants such as
|
//
|
||||||
// Infof. It also provides V-style logging controlled by the -v and -vmodule=file=2 flags.
|
// - output routing as defined via command line flags ([InitFlags])
|
||||||
|
// - log formatting as text, either with a single, unstructured string ([Info], [Infof], etc.)
|
||||||
|
// or as a structured log entry with message and key/value pairs ([InfoS], etc.)
|
||||||
|
// - management of a go-logr [Logger] ([SetLogger], [Background], [TODO])
|
||||||
|
// - helper functions for logging values ([Format]) and managing the state of klog ([CaptureState], [State.Restore])
|
||||||
|
// - wrappers for [logr] APIs for contextual logging where the wrappers can
|
||||||
|
// be turned into no-ops ([EnableContextualLogging], [NewContext], [FromContext],
|
||||||
|
// [LoggerWithValues], [LoggerWithName]); if the ability to turn off
|
||||||
|
// contextual logging is not needed, then go-logr can also be used directly
|
||||||
|
// - type aliases for go-logr types to simplify imports in code which uses both (e.g. [Logger])
|
||||||
|
// - [k8s.io/klog/v2/textlogger]: a logger which uses the same formatting as klog log with
|
||||||
|
// simpler output routing; beware that it comes with its own command line flags
|
||||||
|
// and does not use the ones from klog
|
||||||
|
// - [k8s.io/klog/v2/ktesting]: per-test output in Go unit tests
|
||||||
|
// - [k8s.io/klog/v2/klogr]: a deprecated, standalone [logr.Logger] on top of the main klog package;
|
||||||
|
// use [Background] instead if klog output routing is needed, [k8s.io/klog/v2/textlogger] if not
|
||||||
|
// - [k8s.io/klog/v2/examples]: demos of this functionality
|
||||||
|
// - [k8s.io/klog/v2/test]: reusable tests for [logr.Logger] implementations
|
||||||
//
|
//
|
||||||
// Basic examples:
|
// Basic examples:
|
||||||
//
|
//
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/go-logr/logr/slogr"
|
"github.com/go-logr/logr"
|
||||||
|
|
||||||
"k8s.io/klog/v2/internal/buffer"
|
"k8s.io/klog/v2/internal/buffer"
|
||||||
"k8s.io/klog/v2/internal/serialize"
|
"k8s.io/klog/v2/internal/serialize"
|
||||||
|
@ -35,7 +35,7 @@ import (
|
||||||
|
|
||||||
func (l *klogger) Handle(ctx context.Context, record slog.Record) error {
|
func (l *klogger) Handle(ctx context.Context, record slog.Record) error {
|
||||||
if logging.logger != nil {
|
if logging.logger != nil {
|
||||||
if slogSink, ok := logging.logger.GetSink().(slogr.SlogSink); ok {
|
if slogSink, ok := logging.logger.GetSink().(logr.SlogSink); ok {
|
||||||
// Let that logger do the work.
|
// Let that logger do the work.
|
||||||
return slogSink.Handle(ctx, record)
|
return slogSink.Handle(ctx, record)
|
||||||
}
|
}
|
||||||
|
@ -77,13 +77,13 @@ func slogOutput(file string, line int, now time.Time, err error, s severity.Seve
|
||||||
buffer.PutBuffer(b)
|
buffer.PutBuffer(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *klogger) WithAttrs(attrs []slog.Attr) slogr.SlogSink {
|
func (l *klogger) WithAttrs(attrs []slog.Attr) logr.SlogSink {
|
||||||
clone := *l
|
clone := *l
|
||||||
clone.values = serialize.WithValues(l.values, sloghandler.Attrs2KVList(l.groups, attrs))
|
clone.values = serialize.WithValues(l.values, sloghandler.Attrs2KVList(l.groups, attrs))
|
||||||
return &clone
|
return &clone
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *klogger) WithGroup(name string) slogr.SlogSink {
|
func (l *klogger) WithGroup(name string) logr.SlogSink {
|
||||||
clone := *l
|
clone := *l
|
||||||
if clone.groups != "" {
|
if clone.groups != "" {
|
||||||
clone.groups += "." + name
|
clone.groups += "." + name
|
||||||
|
@ -93,4 +93,4 @@ func (l *klogger) WithGroup(name string) slogr.SlogSink {
|
||||||
return &clone
|
return &clone
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ slogr.SlogSink = &klogger{}
|
var _ logr.SlogSink = &klogger{}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
//go:build go1.18
|
||||||
|
// +build go1.18
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 2023 The Kubernetes 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 klog
|
||||||
|
|
||||||
|
// SafePtr is a function that takes a pointer of any type (T) as an argument.
|
||||||
|
// If the provided pointer is not nil, it returns the same pointer. If it is nil, it returns nil instead.
|
||||||
|
//
|
||||||
|
// This function is particularly useful to prevent nil pointer dereferencing when:
|
||||||
|
//
|
||||||
|
// - The type implements interfaces that are called by the logger, such as `fmt.Stringer`.
|
||||||
|
// - And these interface implementations do not perform nil checks themselves.
|
||||||
|
func SafePtr[T any](p *T) any {
|
||||||
|
if p == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return p
|
||||||
|
}
|
|
@ -55,7 +55,7 @@ github.com/coreos/go-systemd/v22/journal
|
||||||
# github.com/cpuguy83/go-md2man/v2 v2.0.3
|
# github.com/cpuguy83/go-md2man/v2 v2.0.3
|
||||||
## explicit; go 1.11
|
## explicit; go 1.11
|
||||||
github.com/cpuguy83/go-md2man/v2/md2man
|
github.com/cpuguy83/go-md2man/v2/md2man
|
||||||
# github.com/davecgh/go-spew v1.1.1
|
# github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
|
||||||
## explicit
|
## explicit
|
||||||
github.com/davecgh/go-spew/spew
|
github.com/davecgh/go-spew/spew
|
||||||
# github.com/distribution/reference v0.5.0
|
# github.com/distribution/reference v0.5.0
|
||||||
|
@ -107,7 +107,6 @@ github.com/go-errors/errors
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
github.com/go-logr/logr
|
github.com/go-logr/logr
|
||||||
github.com/go-logr/logr/funcr
|
github.com/go-logr/logr/funcr
|
||||||
github.com/go-logr/logr/slogr
|
|
||||||
# github.com/go-logr/stdr v1.2.2
|
# github.com/go-logr/stdr v1.2.2
|
||||||
## explicit; go 1.16
|
## explicit; go 1.16
|
||||||
github.com/go-logr/stdr
|
github.com/go-logr/stdr
|
||||||
|
@ -212,8 +211,8 @@ github.com/google/go-cmp/cmp/internal/value
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/google/gofuzz
|
github.com/google/gofuzz
|
||||||
github.com/google/gofuzz/bytesource
|
github.com/google/gofuzz/bytesource
|
||||||
# github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1
|
# github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98
|
||||||
## explicit; go 1.14
|
## explicit; go 1.19
|
||||||
github.com/google/pprof/profile
|
github.com/google/pprof/profile
|
||||||
# github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2
|
# github.com/google/safetext v0.0.0-20220905092116-b49f7bc46da2
|
||||||
## explicit; go 1.19
|
## explicit; go 1.19
|
||||||
|
@ -289,9 +288,6 @@ github.com/mattn/go-isatty
|
||||||
# github.com/mattn/go-runewidth v0.0.14
|
# github.com/mattn/go-runewidth v0.0.14
|
||||||
## explicit; go 1.9
|
## explicit; go 1.9
|
||||||
github.com/mattn/go-runewidth
|
github.com/mattn/go-runewidth
|
||||||
# github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0
|
|
||||||
## explicit; go 1.19
|
|
||||||
github.com/matttproud/golang_protobuf_extensions/v2/pbutil
|
|
||||||
# github.com/mitchellh/go-homedir v1.1.0
|
# github.com/mitchellh/go-homedir v1.1.0
|
||||||
## explicit
|
## explicit
|
||||||
github.com/mitchellh/go-homedir
|
github.com/mitchellh/go-homedir
|
||||||
|
@ -327,7 +323,7 @@ github.com/mxk/go-flowrate/flowrate
|
||||||
# github.com/olekukonko/tablewriter v0.0.5
|
# github.com/olekukonko/tablewriter v0.0.5
|
||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/olekukonko/tablewriter
|
github.com/olekukonko/tablewriter
|
||||||
# github.com/onsi/ginkgo/v2 v2.13.0
|
# github.com/onsi/ginkgo/v2 v2.14.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
github.com/onsi/ginkgo/v2
|
github.com/onsi/ginkgo/v2
|
||||||
github.com/onsi/ginkgo/v2/config
|
github.com/onsi/ginkgo/v2/config
|
||||||
|
@ -349,7 +345,7 @@ github.com/onsi/ginkgo/v2/internal/parallel_support
|
||||||
github.com/onsi/ginkgo/v2/internal/testingtproxy
|
github.com/onsi/ginkgo/v2/internal/testingtproxy
|
||||||
github.com/onsi/ginkgo/v2/reporters
|
github.com/onsi/ginkgo/v2/reporters
|
||||||
github.com/onsi/ginkgo/v2/types
|
github.com/onsi/ginkgo/v2/types
|
||||||
# github.com/onsi/gomega v1.29.0
|
# github.com/onsi/gomega v1.30.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
github.com/onsi/gomega
|
github.com/onsi/gomega
|
||||||
github.com/onsi/gomega/format
|
github.com/onsi/gomega/format
|
||||||
|
@ -402,7 +398,7 @@ github.com/prometheus/client_golang/prometheus/testutil/promlint/validations
|
||||||
# github.com/prometheus/client_model v0.5.0
|
# github.com/prometheus/client_model v0.5.0
|
||||||
## explicit; go 1.19
|
## explicit; go 1.19
|
||||||
github.com/prometheus/client_model/go
|
github.com/prometheus/client_model/go
|
||||||
# github.com/prometheus/common v0.45.0
|
# github.com/prometheus/common v0.46.0
|
||||||
## explicit; go 1.20
|
## explicit; go 1.20
|
||||||
github.com/prometheus/common/expfmt
|
github.com/prometheus/common/expfmt
|
||||||
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
|
github.com/prometheus/common/internal/bitbucket.org/ww/goautoneg
|
||||||
|
@ -588,7 +584,7 @@ go.starlark.net/resolve
|
||||||
go.starlark.net/starlark
|
go.starlark.net/starlark
|
||||||
go.starlark.net/starlarkstruct
|
go.starlark.net/starlarkstruct
|
||||||
go.starlark.net/syntax
|
go.starlark.net/syntax
|
||||||
# go.uber.org/atomic v1.10.0
|
# go.uber.org/atomic v1.11.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
go.uber.org/atomic
|
go.uber.org/atomic
|
||||||
# go.uber.org/mock v0.4.0
|
# go.uber.org/mock v0.4.0
|
||||||
|
@ -649,7 +645,7 @@ golang.org/x/net/internal/timeseries
|
||||||
golang.org/x/net/proxy
|
golang.org/x/net/proxy
|
||||||
golang.org/x/net/trace
|
golang.org/x/net/trace
|
||||||
golang.org/x/net/websocket
|
golang.org/x/net/websocket
|
||||||
# golang.org/x/oauth2 v0.15.0
|
# golang.org/x/oauth2 v0.16.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
golang.org/x/oauth2
|
golang.org/x/oauth2
|
||||||
golang.org/x/oauth2/internal
|
golang.org/x/oauth2/internal
|
||||||
|
@ -809,6 +805,7 @@ google.golang.org/grpc/status
|
||||||
google.golang.org/grpc/tap
|
google.golang.org/grpc/tap
|
||||||
# google.golang.org/protobuf v1.33.0
|
# google.golang.org/protobuf v1.33.0
|
||||||
## explicit; go 1.17
|
## explicit; go 1.17
|
||||||
|
google.golang.org/protobuf/encoding/protodelim
|
||||||
google.golang.org/protobuf/encoding/protojson
|
google.golang.org/protobuf/encoding/protojson
|
||||||
google.golang.org/protobuf/encoding/prototext
|
google.golang.org/protobuf/encoding/prototext
|
||||||
google.golang.org/protobuf/encoding/protowire
|
google.golang.org/protobuf/encoding/protowire
|
||||||
|
@ -1584,8 +1581,8 @@ k8s.io/gengo/generator
|
||||||
k8s.io/gengo/namer
|
k8s.io/gengo/namer
|
||||||
k8s.io/gengo/parser
|
k8s.io/gengo/parser
|
||||||
k8s.io/gengo/types
|
k8s.io/gengo/types
|
||||||
# k8s.io/klog/v2 v2.110.1
|
# k8s.io/klog/v2 v2.120.0
|
||||||
## explicit; go 1.13
|
## explicit; go 1.18
|
||||||
k8s.io/klog/v2
|
k8s.io/klog/v2
|
||||||
k8s.io/klog/v2/internal/buffer
|
k8s.io/klog/v2/internal/buffer
|
||||||
k8s.io/klog/v2/internal/clock
|
k8s.io/klog/v2/internal/clock
|
||||||
|
@ -1948,8 +1945,8 @@ sigs.k8s.io/kustomize/kyaml/yaml/walk
|
||||||
# sigs.k8s.io/mcs-api v0.1.0
|
# sigs.k8s.io/mcs-api v0.1.0
|
||||||
## explicit; go 1.14
|
## explicit; go 1.14
|
||||||
sigs.k8s.io/mcs-api/pkg/apis/v1alpha1
|
sigs.k8s.io/mcs-api/pkg/apis/v1alpha1
|
||||||
# sigs.k8s.io/metrics-server v0.6.1-0.20230706083104-796fc0f832c1
|
# sigs.k8s.io/metrics-server v0.7.1
|
||||||
## explicit; go 1.20
|
## explicit; go 1.21
|
||||||
sigs.k8s.io/metrics-server/pkg/api
|
sigs.k8s.io/metrics-server/pkg/api
|
||||||
# sigs.k8s.io/structured-merge-diff/v4 v4.4.1
|
# sigs.k8s.io/structured-merge-diff/v4 v4.4.1
|
||||||
## explicit; go 1.13
|
## explicit; go 1.13
|
||||||
|
|
|
@ -178,5 +178,5 @@ func (m *nodeMetrics) NamespaceScoped() bool {
|
||||||
|
|
||||||
// GetSingularName implements rest.SingularNameProvider interface
|
// GetSingularName implements rest.SingularNameProvider interface
|
||||||
func (m *nodeMetrics) GetSingularName() string {
|
func (m *nodeMetrics) GetSingularName() string {
|
||||||
return "node"
|
return ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -185,5 +185,5 @@ func (m *podMetrics) NamespaceScoped() bool {
|
||||||
|
|
||||||
// GetSingularName implements rest.SingularNameProvider interface
|
// GetSingularName implements rest.SingularNameProvider interface
|
||||||
func (m *podMetrics) GetSingularName() string {
|
func (m *podMetrics) GetSingularName() string {
|
||||||
return "pod"
|
return ""
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue