diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2172de9..4b43b3d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,6 +33,7 @@ jobs: with: # We need all tags fetch-depth: 0 + fetch-tags: true - name: Set up Go uses: actions/setup-go@v4 with: diff --git a/CHANGELOG.md b/CHANGELOG.md index 671268e..d5fe324 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,18 +8,48 @@ versioning](https://go.dev/doc/modules/version-numbers). ## [Unreleased](https://github.com/autometrics-dev/autometrics-go/compare/v0.8.2...main) +The main goal of this release is to reach compatibility with 1.0.0 version of Autometrics +specification. + ### Added +- [All] `autometrics` now also optionnally adds the repository where the code comes from + in the `build_info` metric. `repository.url` and `repository.provider` can be either + set in the `BuildInformation` structure when calling `autometrics.Init`, or by setting + environment variables `AUTOMETRICS_REPOSITORY_URL` and `AUTOMETRICS_REPOSITORY_PROVIDER`, + respectively. + ### Changed +- [All] `autometrics` now inserts 2 statements in each function it instruments. The context + created to track the function execution is now put in a variable, so that callees in the + function body can optionnally use the context to help with better trace/span/call graph + tracking. If `autometrics` detects a `context.Context` it can use, it will shadow the + context with the autometrics augmented one to reduce the changes to make in the code. + Currently, `autometrics` can detect arguments of specific types in the function signatures + to read from and replace contexts: + + `context.Context` (read and replace) + + `http.Request` (read only) + + `buffalo.Request` (read and replace) + + `gin.Context` (read only; _very_ experimental) +- [Generator] The generator now tries to keep going with instrumentation even if some instrumentation + fails. On error, still _No file will be modified_, and the generator will exit with an error code + and output all the collected errors instead of only the first one. + ### Deprecated ### Removed ### Fixed +- [Generator] Fix a few generator crashes when instrumented functions have specific argument types. + ### Security +- Update all dependencies to reduce dependabot alerts in + + `google.golang.org/grpc` + + `golang.org/x/net` + ## [0.8.2](https://github.com/autometrics-dev/autometrics-go/releases/tag/v0.8.2) 2023-10-20 ### Added diff --git a/cmd/autometrics/main.go b/cmd/autometrics/main.go index 181aa40..6020879 100644 --- a/cmd/autometrics/main.go +++ b/cmd/autometrics/main.go @@ -31,7 +31,11 @@ type args struct { func (args) Version() string { var buf strings.Builder - fmt.Fprintf(&buf, "Autometrics %s", build.Version) + fmt.Fprintf(&buf, "Autometrics %s (built by %s on %s)", + build.Version, + build.User, + build.Time, + ) return buf.String() } diff --git a/examples/otel/cmd/main.go b/examples/otel/cmd/main.go index 8e56a1e..60a63ed 100644 --- a/examples/otel/cmd/main.go +++ b/examples/otel/cmd/main.go @@ -98,13 +98,14 @@ func main() { // //autometrics:doc --slo "API" --latency-target 99 --latency-ms 5 func indexHandler(w http.ResponseWriter, r *http.Request) error { - defer autometrics.Instrument(autometrics.PreInstrument(autometrics.NewContext( + amCtx := autometrics.PreInstrument(autometrics.NewContext( r.Context(), autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertLatency(5000000*time.Nanosecond, 99), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer autometrics.Instrument(amCtx, nil) //autometrics:defer msSleep := rand.Intn(200) time.Sleep(time.Duration(msSleep) * time.Millisecond) @@ -148,13 +149,14 @@ var handlerError = errors.New("failed to handle request") // //autometrics:doc --slo "API" --success-target 90 func randomErrorHandler(w http.ResponseWriter, r *http.Request) (err error) { - defer autometrics.Instrument(autometrics.PreInstrument(autometrics.NewContext( + amCtx := autometrics.PreInstrument(autometrics.NewContext( r.Context(), autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertSuccess(90), - )), &err) //autometrics:defer + )) //autometrics:shadow-ctx + defer autometrics.Instrument(amCtx, &err) //autometrics:defer isOk := rand.Intn(10) == 0 diff --git a/examples/otel/go.mod b/examples/otel/go.mod index a04829c..7d2b832 100644 --- a/examples/otel/go.mod +++ b/examples/otel/go.mod @@ -4,38 +4,38 @@ go 1.20 require ( github.com/autometrics-dev/autometrics-go v0.0.0-20230222105517-4997cc8aa1e4 - github.com/prometheus/client_golang v1.16.0 + github.com/prometheus/client_golang v1.17.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/oklog/ulid/v2 v2.1.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect - go.opentelemetry.io/otel v1.17.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.40.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.40.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.40.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.40.0 // indirect - go.opentelemetry.io/otel/metric v1.17.0 // indirect - go.opentelemetry.io/otel/sdk v1.17.0 // indirect - go.opentelemetry.io/otel/sdk/metric v0.40.0 // indirect - go.opentelemetry.io/otel/trace v1.17.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + go.opentelemetry.io/otel v1.19.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.42.0 // indirect + go.opentelemetry.io/otel/metric v1.19.0 // indirect + go.opentelemetry.io/otel/sdk v1.19.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.19.0 // indirect + go.opentelemetry.io/otel/trace v1.19.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/text v0.9.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/grpc v1.57.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/grpc v1.59.0 // indirect google.golang.org/protobuf v1.31.0 // indirect ) diff --git a/examples/otel/go.sum b/examples/otel/go.sum index 1e9ccc7..4a2e426 100644 --- a/examples/otel/go.sum +++ b/examples/otel/go.sum @@ -6,69 +6,67 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= +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/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM= -go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.40.0 h1:MZbjiZeMmn5wFMORhozpouGKDxj9POHTuU5UA8msBQk= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.40.0/go.mod h1:C7tOYVCJmrDTCwxNny0MuUtnDIR3032vFHYke0F2ZrU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.40.0 h1:q3FNPi8FLQVjLlmV+WWHQfH9ZCCtQIS0O/+dn1+4cJ4= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.40.0/go.mod h1:rmx4n0uSIAkKBeQYkygcv9dENAlL2/tv3OSq68h1JAo= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.40.0 h1:SZaSbubADNhH2Gxm+1GaZ/cFsGiYefZoodMMX79AOd4= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.40.0/go.mod h1:N65FzQDfQH7NY7umgb0U+7ypGKVYKwwE24L6KXT4OA8= -go.opentelemetry.io/otel/exporters/prometheus v0.40.0 h1:9h6lCssr1j5aYVvWT6oc+ERB6R034zmsHjBRLyxrAR8= -go.opentelemetry.io/otel/exporters/prometheus v0.40.0/go.mod h1:5USWZ0ovyQB5CIM3IO3bGRSoDPMXiT3t+15gu8Zo9HQ= -go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc= -go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= -go.opentelemetry.io/otel/sdk v1.17.0 h1:FLN2X66Ke/k5Sg3V623Q7h7nt3cHXaW1FOvKKrW0IpE= -go.opentelemetry.io/otel/sdk v1.17.0/go.mod h1:U87sE0f5vQB7hwUoW98pW5Rz4ZDuCFBZFNUBlSgmDFQ= -go.opentelemetry.io/otel/sdk/metric v0.40.0 h1:qOM29YaGcxipWjL5FzpyZDpCYrDREvX0mVlmXdOjCHU= -go.opentelemetry.io/otel/sdk/metric v0.40.0/go.mod h1:dWxHtdzdJvg+ciJUKLTKwrMe5P6Dv3FyDbh8UkfgkVs= -go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ= -go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 h1:wNMDy/LVGLj2h3p6zg4d0gypKfWKSWI14E1C4smOgl8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0/go.mod h1:YfbDdXAAkemWJK3H/DshvlrxqFB2rtW4rY6ky/3x/H0= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0 h1:jwV9iQdvp38fxXi8ZC+lNpxjK16MRcZlpDYvbuO1FiA= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0/go.mod h1:f3bYiqNqhoPxkvI2LrXqQVC546K7BuRDL/kKuxkujhA= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= +go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= +go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= -google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= +google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405 h1:HJMDndgxest5n2y77fnErkM62iUsptE/H8p0dC2Huo4= +google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405/go.mod h1:oT32Z4o8Zv2xPQTg0pbVaPr0MPOH6f14RgXt7zfIpwg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= diff --git a/examples/web/cmd/main.go b/examples/web/cmd/main.go index f420007..99e0485 100644 --- a/examples/web/cmd/main.go +++ b/examples/web/cmd/main.go @@ -98,22 +98,23 @@ func main() { // // autometrics:doc-end Generated documentation by Autometrics. // -// [Request Rate]: http://localhost:9090/graph?g0.expr=%23+Rate+of+calls+to+the+%60indexHandler%60+function+per+second%2C+averaged+over+5+minute+windows%0A%0Asum+by+%28function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_count%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29&g0.tab=0 -// [Error Ratio]: http://localhost:9090/graph?g0.expr=%23+Percentage+of+calls+to+the+%60indexHandler%60+function+that+return+errors%2C+averaged+over+5+minute+windows%0A%0A%28sum+by+%28function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_count%7Bfunction%3D%22indexHandler%22%2Cresult%3D%22error%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29+%2F+%28sum+by+%28function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_count%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29&g0.tab=0 -// [Latency (95th and 99th percentiles)]: http://localhost:9090/graph?g0.expr=%23+95th+and+99th+percentile+latencies+%28in+seconds%29+for+the+%60indexHandler%60+function%0A%0Alabel_replace%28histogram_quantile%280.99%2C+sum+by+%28le%2C+function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_duration_bucket%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29%2C+%22percentile_latency%22%2C+%2299%22%2C+%22%22%2C+%22%22%29+or+label_replace%28histogram_quantile%280.95%2C+sum+by+%28le%2C+function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_duration_bucket%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29%2C%22percentile_latency%22%2C+%2295%22%2C+%22%22%2C+%22%22%29&g0.tab=0 -// [Concurrent Calls]: http://localhost:9090/graph?g0.expr=%23+Concurrent+calls+to+the+%60indexHandler%60+function%0A%0Asum+by+%28function%2C+module%2C+version%2C+commit%29+%28function_calls_concurrent%7Bfunction%3D%22indexHandler%22%7D+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29&g0.tab=0 -// [Request Rate Callee]: http://localhost:9090/graph?g0.expr=%23+Rate+of+function+calls+emanating+from+%60indexHandler%60+function+per+second%2C+averaged+over+5+minute+windows%0A%0Asum+by+%28function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_count%7Bcaller%3D%22main.indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29&g0.tab=0 -// [Error Ratio Callee]: http://localhost:9090/graph?g0.expr=%23+Percentage+of+function+emanating+from+%60indexHandler%60+function+that+return+errors%2C+averaged+over+5+minute+windows%0A%0A%28sum+by+%28function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_count%7Bcaller%3D%22main.indexHandler%22%2Cresult%3D%22error%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29+%2F+%28sum+by+%28function%2C+module%2C+version%2C+commit%29+%28rate%28function_calls_count%7Bcaller%3D%22main.indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29&g0.tab=0 +// [Request Rate]: http://localhost:9090/graph?g0.expr=%23+Rate+of+calls+to+the+%60indexHandler%60+function+per+second%2C+averaged+over+5+minute+windows%0A%0Asum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29&g0.tab=0 +// [Error Ratio]: http://localhost:9090/graph?g0.expr=%23+Percentage+of+calls+to+the+%60indexHandler%60+function+that+return+errors%2C+averaged+over+5+minute+windows%0A%0A%28sum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bfunction%3D%22indexHandler%22%2Cresult%3D%22error%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29+%2F+%28sum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29&g0.tab=0 +// [Latency (95th and 99th percentiles)]: http://localhost:9090/graph?g0.expr=%23+95th+and+99th+percentile+latencies+%28in+seconds%29+for+the+%60indexHandler%60+function%0A%0Alabel_replace%28histogram_quantile%280.99%2C+sum+by+%28le%2C+function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_duration_seconds_bucket%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29%2C+%22percentile_latency%22%2C+%2299%22%2C+%22%22%2C+%22%22%29+or+label_replace%28histogram_quantile%280.95%2C+sum+by+%28le%2C+function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_duration_seconds_bucket%7Bfunction%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29%2C%22percentile_latency%22%2C+%2295%22%2C+%22%22%2C+%22%22%29&g0.tab=0 +// [Concurrent Calls]: http://localhost:9090/graph?g0.expr=%23+Concurrent+calls+to+the+%60indexHandler%60+function%0A%0Asum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28function_calls_concurrent%7Bfunction%3D%22indexHandler%22%7D+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29&g0.tab=0 +// [Request Rate Callee]: http://localhost:9090/graph?g0.expr=%23+Rate+of+function+calls+emanating+from+%60indexHandler%60+function+per+second%2C+averaged+over+5+minute+windows%0A%0Asum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bcaller_function%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29&g0.tab=0 +// [Error Ratio Callee]: http://localhost:9090/graph?g0.expr=%23+Percentage+of+function+emanating+from+%60indexHandler%60+function+that+return+errors%2C+averaged+over+5+minute+windows%0A%0A%28sum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bcaller_function%3D%22indexHandler%22%2Cresult%3D%22error%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29+%2F+%28sum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bcaller_function%3D%22indexHandler%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29&g0.tab=0 // //autometrics:inst --slo "API" --latency-target 99 --latency-ms 5 func indexHandler(w http.ResponseWriter, r *http.Request) error { - defer autometrics.Instrument(autometrics.PreInstrument(autometrics.NewContext( + amCtx := autometrics.PreInstrument(autometrics.NewContext( r.Context(), autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertLatency(5000000*time.Nanosecond, 99), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer autometrics.Instrument(amCtx, nil) //autometrics:defer msSleep := rand.Intn(200) time.Sleep(time.Duration(msSleep) * time.Millisecond) diff --git a/examples/web/go.mod b/examples/web/go.mod index 06b0876..a635b09 100644 --- a/examples/web/go.mod +++ b/examples/web/go.mod @@ -4,19 +4,18 @@ go 1.20 require ( github.com/autometrics-dev/autometrics-go v0.0.0-20230222105517-4997cc8aa1e4 - github.com/prometheus/client_golang v1.16.0 + github.com/prometheus/client_golang v1.17.0 ) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/oklog/ulid/v2 v2.1.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 // indirect - github.com/prometheus/procfs v0.11.1 // indirect - golang.org/x/sys v0.12.0 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect + golang.org/x/sys v0.13.0 // indirect google.golang.org/protobuf v1.31.0 // indirect ) diff --git a/examples/web/go.sum b/examples/web/go.sum index 43a8652..245c067 100644 --- a/examples/web/go.sum +++ b/examples/web/go.sum @@ -3,30 +3,25 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +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/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= -github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= diff --git a/go.mod b/go.mod index 02c3710..71b3914 100644 --- a/go.mod +++ b/go.mod @@ -2,54 +2,55 @@ module github.com/autometrics-dev/autometrics-go go 1.18 -require github.com/prometheus/client_golang v1.16.0 +require github.com/prometheus/client_golang v1.17.0 require ( github.com/alexflint/go-arg v1.4.3 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/oklog/ulid/v2 v2.1.0 - go.opentelemetry.io/otel v1.17.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.40.0 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.40.0 - go.opentelemetry.io/otel/exporters/prometheus v0.40.0 - go.opentelemetry.io/otel/metric v1.17.0 - go.opentelemetry.io/otel/sdk v1.17.0 - go.opentelemetry.io/otel/sdk/metric v0.40.0 - golang.org/x/exp v0.0.0-20230223210539-50820d90acfd + go.opentelemetry.io/otel v1.19.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 + go.opentelemetry.io/otel/exporters/prometheus v0.42.0 + go.opentelemetry.io/otel/metric v1.19.0 + go.opentelemetry.io/otel/sdk v1.19.0 + go.opentelemetry.io/otel/sdk/metric v1.19.0 + golang.org/x/exp v0.0.0-20231006140011-7918f672742d ) require ( - github.com/alexflint/go-scalar v1.1.0 // indirect + github.com/alexflint/go-scalar v1.2.0 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect - github.com/go-logr/logr v1.2.4 // indirect + github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.40.0 // indirect - go.opentelemetry.io/otel/trace v1.17.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 // indirect + go.opentelemetry.io/otel/trace v1.19.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/text v0.9.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // indirect - google.golang.org/grpc v1.57.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/text v0.13.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 // indirect + google.golang.org/grpc v1.59.0 // indirect ) require ( github.com/beorn7/perks v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect - github.com/dave/dst v0.27.2 + github.com/dave/dst v0.27.3 github.com/dave/jennifer v1.6.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.4.0 // indirect - github.com/prometheus/common v0.44.0 - github.com/prometheus/procfs v0.11.1 // indirect + github.com/prometheus/client_model v0.5.0 // indirect + github.com/prometheus/common v0.45.0 + github.com/prometheus/procfs v0.12.0 // indirect github.com/stretchr/testify v1.8.4 - golang.org/x/mod v0.8.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/tools v0.6.0 // indirect + golang.org/x/mod v0.13.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/tools v0.14.0 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 9b7195e..834caeb 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ github.com/alexflint/go-arg v1.4.3 h1:9rwwEBpMXfKQKceuZfYcwuc/7YY7tWJbFsgG5cAU/u github.com/alexflint/go-arg v1.4.3/go.mod h1:3PZ/wp/8HuqRZMUUgu7I+e1qcpUbvmS258mRXkFH4IA= github.com/alexflint/go-scalar v1.1.0 h1:aaAouLLzI9TChcPXotr6gUhq+Scr8rl0P9P4PnltbhM= github.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= +github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw= +github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= @@ -10,6 +12,8 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/dave/dst v0.27.2 h1:4Y5VFTkhGLC1oddtNwuxxe36pnyLxMFXT51FOzH8Ekc= github.com/dave/dst v0.27.2/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEyc= +github.com/dave/dst v0.27.3 h1:P1HPoMza3cMEquVf9kKy8yXsFirry4zEnWOdYPOoIzY= +github.com/dave/dst v0.27.3/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEyc= github.com/dave/jennifer v1.6.0 h1:MQ/6emI2xM7wt0tJzJzyUik2Q3Tcn2eE0vtYgh4GPVI= github.com/dave/jennifer v1.6.0/go.mod h1:AxTG893FiZKqxy3FP1kL80VMshSMuz2G+EgvszgGRnk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -18,9 +22,12 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/golang/glog v1.1.0 h1:/d3pCKDPWNnvIWe0vVUpNP32qc8U3PDVxySP/y360qE= +github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= @@ -31,10 +38,14 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +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/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= @@ -42,12 +53,20 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -57,46 +76,84 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= go.opentelemetry.io/otel v1.17.0 h1:MW+phZ6WZ5/uk2nd93ANk/6yJ+dVrvNWUjGhnnFU5jM= go.opentelemetry.io/otel v1.17.0/go.mod h1:I2vmBGtFaODIVMBSTPVDlJSzBDNf93k60E6Ft0nyjo0= +go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= +go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.40.0 h1:MZbjiZeMmn5wFMORhozpouGKDxj9POHTuU5UA8msBQk= go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.40.0/go.mod h1:C7tOYVCJmrDTCwxNny0MuUtnDIR3032vFHYke0F2ZrU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.40.0 h1:q3FNPi8FLQVjLlmV+WWHQfH9ZCCtQIS0O/+dn1+4cJ4= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.40.0/go.mod h1:rmx4n0uSIAkKBeQYkygcv9dENAlL2/tv3OSq68h1JAo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.40.0 h1:SZaSbubADNhH2Gxm+1GaZ/cFsGiYefZoodMMX79AOd4= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.40.0/go.mod h1:N65FzQDfQH7NY7umgb0U+7ypGKVYKwwE24L6KXT4OA8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 h1:wNMDy/LVGLj2h3p6zg4d0gypKfWKSWI14E1C4smOgl8= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0/go.mod h1:YfbDdXAAkemWJK3H/DshvlrxqFB2rtW4rY6ky/3x/H0= go.opentelemetry.io/otel/exporters/prometheus v0.40.0 h1:9h6lCssr1j5aYVvWT6oc+ERB6R034zmsHjBRLyxrAR8= go.opentelemetry.io/otel/exporters/prometheus v0.40.0/go.mod h1:5USWZ0ovyQB5CIM3IO3bGRSoDPMXiT3t+15gu8Zo9HQ= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0 h1:jwV9iQdvp38fxXi8ZC+lNpxjK16MRcZlpDYvbuO1FiA= +go.opentelemetry.io/otel/exporters/prometheus v0.42.0/go.mod h1:f3bYiqNqhoPxkvI2LrXqQVC546K7BuRDL/kKuxkujhA= go.opentelemetry.io/otel/metric v1.17.0 h1:iG6LGVz5Gh+IuO0jmgvpTB6YVrCGngi8QGm+pMd8Pdc= go.opentelemetry.io/otel/metric v1.17.0/go.mod h1:h4skoxdZI17AxwITdmdZjjYJQH5nzijUUjm+wtPph5o= +go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= +go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= go.opentelemetry.io/otel/sdk v1.17.0 h1:FLN2X66Ke/k5Sg3V623Q7h7nt3cHXaW1FOvKKrW0IpE= go.opentelemetry.io/otel/sdk v1.17.0/go.mod h1:U87sE0f5vQB7hwUoW98pW5Rz4ZDuCFBZFNUBlSgmDFQ= +go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= +go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= go.opentelemetry.io/otel/sdk/metric v0.40.0 h1:qOM29YaGcxipWjL5FzpyZDpCYrDREvX0mVlmXdOjCHU= go.opentelemetry.io/otel/sdk/metric v0.40.0/go.mod h1:dWxHtdzdJvg+ciJUKLTKwrMe5P6Dv3FyDbh8UkfgkVs= +go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8Ni+hx+8i1k= +go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY= go.opentelemetry.io/otel/trace v1.17.0 h1:/SWhSRHmDPOImIAetP1QAeMnZYiQXrTy4fMMYOdSKWQ= go.opentelemetry.io/otel/trace v1.17.0/go.mod h1:I/4vKTgFclIsXRVucpH25X0mpFSczM7aHeaz0ZBLWjY= +go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= +go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= golang.org/x/exp v0.0.0-20230223210539-50820d90acfd h1:wtFuj4DoOcAdb82Zh2PI90xiaqgp7maYA7KxjQXVtkY= golang.org/x/exp v0.0.0-20230223210539-50820d90acfd/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e h1:Ao9GzfUMPH3zjVfzXG5rlWlk+Q8MXWKwWpwVQE1MXfw= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b h1:+YaDE2r2OG8t/z5qmsh7Y+XXwCbvadxxZ0YY6mTdrVA= google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc h1:kVKPf/IiYSBWEWtkIn6wZXwWGCnLKcC8oWfZvXjsGnM= google.golang.org/genproto/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405 h1:HJMDndgxest5n2y77fnErkM62iUsptE/H8p0dC2Huo4= +google.golang.org/genproto/googleapis/api v0.0.0-20231030173426-d783a09b4405/go.mod h1:oT32Z4o8Zv2xPQTg0pbVaPr0MPOH6f14RgXt7zfIpwg= google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc h1:XSJ8Vk1SWuNr8S18z1NZSziL0CPIXLCCMDOEFtHBOFc= google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405 h1:AB/lmRny7e2pLhFEYIbl5qkDAUt2h0ZRO4wGPhZf+ik= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231030173426-d783a09b4405/go.mod h1:67X1fPuzjcrkymZzZV1vvkFeTn2Rvc6lYF9MYFGCcwE= google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= diff --git a/go.work.sum b/go.work.sum index f5a8d42..cf32a8a 100644 --- a/go.work.sum +++ b/go.work.sum @@ -1,137 +1,269 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= +cloud.google.com/go v0.110.2/go.mod h1:k04UEeEtb6ZBRTv3dZz4CeJC3jKGxyhl0sAiVVquxiw= +cloud.google.com/go v0.110.8/go.mod h1:Iz8AkXJf1qmxC3Oxoep8R1T36w8B92yU29PcBhHO5fk= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= +cloud.google.com/go/accessapproval v1.7.2/go.mod h1:/gShiq9/kK/h8T/eEn1BTzalDvk0mZxJlhfw0p+Xuc0= cloud.google.com/go/accesscontextmanager v1.7.0/go.mod h1:CEGLewx8dwa33aDAZQujl7Dx+uYhS0eay198wB/VumQ= +cloud.google.com/go/accesscontextmanager v1.8.2/go.mod h1:E6/SCRM30elQJ2PKtFMs2YhfJpZSNcJyejhuzoId4Zk= cloud.google.com/go/aiplatform v1.37.0/go.mod h1:IU2Cv29Lv9oCn/9LkFiiuKfwrRTq+QQMbW+hPCxJGZw= +cloud.google.com/go/aiplatform v1.51.1/go.mod h1:kY3nIMAVQOK2XDqDPHaOuD9e+FdMA6OOpfBjsvaFSOo= cloud.google.com/go/analytics v0.19.0/go.mod h1:k8liqf5/HCnOUkbawNtrWWc+UAzyDlW89doe8TtoDsE= +cloud.google.com/go/analytics v0.21.4/go.mod h1:zZgNCxLCy8b2rKKVfC1YkC2vTrpfZmeRCySM3aUbskA= cloud.google.com/go/apigateway v1.5.0/go.mod h1:GpnZR3Q4rR7LVu5951qfXPJCHquZt02jf7xQx7kpqN8= +cloud.google.com/go/apigateway v1.6.2/go.mod h1:CwMC90nnZElorCW63P2pAYm25AtQrHfuOkbRSHj0bT8= cloud.google.com/go/apigeeconnect v1.5.0/go.mod h1:KFaCqvBRU6idyhSNyn3vlHXc8VMDJdRmwDF6JyFRqZ8= +cloud.google.com/go/apigeeconnect v1.6.2/go.mod h1:s6O0CgXT9RgAxlq3DLXvG8riw8PYYbU/v25jqP3Dy18= cloud.google.com/go/apigeeregistry v0.6.0/go.mod h1:BFNzW7yQVLZ3yj0TKcwzb8n25CFBri51GVGOEUcgQsc= +cloud.google.com/go/apigeeregistry v0.7.2/go.mod h1:9CA2B2+TGsPKtfi3F7/1ncCCsL62NXBRfM6iPoGSM+8= cloud.google.com/go/appengine v1.7.1/go.mod h1:IHLToyb/3fKutRysUlFO0BPt5j7RiQ45nrzEJmKTo6E= +cloud.google.com/go/appengine v1.8.2/go.mod h1:WMeJV9oZ51pvclqFN2PqHoGnys7rK0rz6s3Mp6yMvDo= cloud.google.com/go/area120 v0.7.1/go.mod h1:j84i4E1RboTWjKtZVWXPqvK5VHQFJRF2c1Nm69pWm9k= +cloud.google.com/go/area120 v0.8.2/go.mod h1:a5qfo+x77SRLXnCynFWPUZhnZGeSgvQ+Y0v1kSItkh4= cloud.google.com/go/artifactregistry v1.13.0/go.mod h1:uy/LNfoOIivepGhooAUpL1i30Hgee3Cu0l4VTWHUC08= +cloud.google.com/go/artifactregistry v1.14.3/go.mod h1:A2/E9GXnsyXl7GUvQ/2CjHA+mVRoWAXC0brg2os+kNI= cloud.google.com/go/asset v1.13.0/go.mod h1:WQAMyYek/b7NBpYq/K4KJWcRqzoalEsxz/t/dTk4THw= +cloud.google.com/go/asset v1.15.1/go.mod h1:yX/amTvFWRpp5rcFq6XbCxzKT8RJUam1UoboE179jU4= cloud.google.com/go/assuredworkloads v1.10.0/go.mod h1:kwdUQuXcedVdsIaKgKTp9t0UJkE5+PAVNhdQm4ZVq2E= +cloud.google.com/go/assuredworkloads v1.11.2/go.mod h1:O1dfr+oZJMlE6mw0Bp0P1KZSlj5SghMBvTpZqIcUAW4= cloud.google.com/go/automl v1.12.0/go.mod h1:tWDcHDp86aMIuHmyvjuKeeHEGq76lD7ZqfGLN6B0NuU= +cloud.google.com/go/automl v1.13.2/go.mod h1:gNY/fUmDEN40sP8amAX3MaXkxcqPIn7F1UIIPZpy4Mg= cloud.google.com/go/baremetalsolution v0.5.0/go.mod h1:dXGxEkmR9BMwxhzBhV0AioD0ULBmuLZI8CdwalUxuss= +cloud.google.com/go/baremetalsolution v1.2.1/go.mod h1:3qKpKIw12RPXStwQXcbhfxVj1dqQGEvcmA+SX/mUR88= cloud.google.com/go/batch v0.7.0/go.mod h1:vLZN95s6teRUqRQ4s3RLDsH8PvboqBK+rn1oevL159g= +cloud.google.com/go/batch v1.5.1/go.mod h1:RpBuIYLkQu8+CWDk3dFD/t/jOCGuUpkpX+Y0n1Xccs8= cloud.google.com/go/beyondcorp v0.5.0/go.mod h1:uFqj9X+dSfrheVp7ssLTaRHd2EHqSL4QZmH4e8WXGGU= +cloud.google.com/go/beyondcorp v1.0.1/go.mod h1:zl/rWWAFVeV+kx+X2Javly7o1EIQThU4WlkynffL/lk= cloud.google.com/go/bigquery v1.50.0/go.mod h1:YrleYEh2pSEbgTBZYMJ5SuSr0ML3ypjRB1zgf7pvQLU= +cloud.google.com/go/bigquery v1.56.0/go.mod h1:KDcsploXTEY7XT3fDQzMUZlpQLHzE4itubHrnmhUrZA= cloud.google.com/go/billing v1.13.0/go.mod h1:7kB2W9Xf98hP9Sr12KfECgfGclsH3CQR0R08tnRlRbc= +cloud.google.com/go/billing v1.17.2/go.mod h1:u/AdV/3wr3xoRBk5xvUzYMS1IawOAPwQMuHgHMdljDg= cloud.google.com/go/binaryauthorization v1.5.0/go.mod h1:OSe4OU1nN/VswXKRBmciKpo9LulY41gch5c68htf3/Q= +cloud.google.com/go/binaryauthorization v1.7.1/go.mod h1:GTAyfRWYgcbsP3NJogpV3yeunbUIjx2T9xVeYovtURE= cloud.google.com/go/certificatemanager v1.6.0/go.mod h1:3Hh64rCKjRAX8dXgRAyOcY5vQ/fE1sh8o+Mdd6KPgY8= +cloud.google.com/go/certificatemanager v1.7.2/go.mod h1:15SYTDQMd00kdoW0+XY5d9e+JbOPjp24AvF48D8BbcQ= cloud.google.com/go/channel v1.12.0/go.mod h1:VkxCGKASi4Cq7TbXxlaBezonAYpp1GCnKMY6tnMQnLU= +cloud.google.com/go/channel v1.17.1/go.mod h1:xqfzcOZAcP4b/hUDH0GkGg1Sd5to6di1HOJn/pi5uBQ= cloud.google.com/go/cloudbuild v1.9.0/go.mod h1:qK1d7s4QlO0VwfYn5YuClDGg2hfmLZEb4wQGAbIgL1s= +cloud.google.com/go/cloudbuild v1.14.1/go.mod h1:K7wGc/3zfvmYWOWwYTgF/d/UVJhS4pu+HAy7PL7mCsU= cloud.google.com/go/clouddms v1.5.0/go.mod h1:QSxQnhikCLUw13iAbffF2CZxAER3xDGNHjsTAkQJcQA= +cloud.google.com/go/clouddms v1.7.1/go.mod h1:o4SR8U95+P7gZ/TX+YbJxehOCsM+fe6/brlrFquiszk= cloud.google.com/go/cloudtasks v1.10.0/go.mod h1:NDSoTLkZ3+vExFEWu2UJV1arUyzVDAiZtdWcsUyNwBs= +cloud.google.com/go/cloudtasks v1.12.2/go.mod h1:A7nYkjNlW2gUoROg1kvJrQGhJP/38UaWwsnuBDOBVUk= cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= cloud.google.com/go/compute v1.19.0/go.mod h1:rikpw2y+UMidAe9tISo04EHNOIf42RLYF/q8Bs93scU= cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY= cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE= +cloud.google.com/go/compute v1.19.3/go.mod h1:qxvISKp/gYnXkSAD1ppcSOveRAmzxicEv/JlizULFrI= +cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= +cloud.google.com/go/compute v1.23.1/go.mod h1:CqB3xpmPKKt3OJpW2ndFIXnA9A4xAy/F3Xp1ixncW78= cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= +cloud.google.com/go/contactcenterinsights v1.11.1/go.mod h1:FeNP3Kg8iteKM80lMwSk3zZZKVxr+PGnAId6soKuXwE= cloud.google.com/go/container v1.15.0/go.mod h1:ft+9S0WGjAyjDggg5S06DXj+fHJICWg8L7isCQe9pQA= +cloud.google.com/go/container v1.26.1/go.mod h1:5smONjPRUxeEpDG7bMKWfDL4sauswqEtnBK1/KKpR04= cloud.google.com/go/containeranalysis v0.9.0/go.mod h1:orbOANbwk5Ejoom+s+DUCTTJ7IBdBQJDcSylAx/on9s= +cloud.google.com/go/containeranalysis v0.11.1/go.mod h1:rYlUOM7nem1OJMKwE1SadufX0JP3wnXj844EtZAwWLY= cloud.google.com/go/datacatalog v1.13.0/go.mod h1:E4Rj9a5ZtAxcQJlEBTLgMTphfP11/lNaAshpoBgemX8= +cloud.google.com/go/datacatalog v1.18.1/go.mod h1:TzAWaz+ON1tkNr4MOcak8EBHX7wIRX/gZKM+yTVsv+A= cloud.google.com/go/dataflow v0.8.0/go.mod h1:Rcf5YgTKPtQyYz8bLYhFoIV/vP39eL7fWNcSOyFfLJE= +cloud.google.com/go/dataflow v0.9.2/go.mod h1:vBfdBZ/ejlTaYIGB3zB4T08UshH70vbtZeMD+urnUSo= cloud.google.com/go/dataform v0.7.0/go.mod h1:7NulqnVozfHvWUBpMDfKMUESr+85aJsC/2O0o3jWPDE= +cloud.google.com/go/dataform v0.8.2/go.mod h1:X9RIqDs6NbGPLR80tnYoPNiO1w0wenKTb8PxxlhTMKM= cloud.google.com/go/datafusion v1.6.0/go.mod h1:WBsMF8F1RhSXvVM8rCV3AeyWVxcC2xY6vith3iw3S+8= +cloud.google.com/go/datafusion v1.7.2/go.mod h1:62K2NEC6DRlpNmI43WHMWf9Vg/YvN6QVi8EVwifElI0= cloud.google.com/go/datalabeling v0.7.0/go.mod h1:WPQb1y08RJbmpM3ww0CSUAGweL0SxByuW2E+FU+wXcM= +cloud.google.com/go/datalabeling v0.8.2/go.mod h1:cyDvGHuJWu9U/cLDA7d8sb9a0tWLEletStu2sTmg3BE= cloud.google.com/go/dataplex v1.6.0/go.mod h1:bMsomC/aEJOSpHXdFKFGQ1b0TDPIeL28nJObeO1ppRs= +cloud.google.com/go/dataplex v1.10.1/go.mod h1:1MzmBv8FvjYfc7vDdxhnLFNskikkB+3vl475/XdCDhs= cloud.google.com/go/dataproc v1.12.0/go.mod h1:zrF3aX0uV3ikkMz6z4uBbIKyhRITnxvr4i3IjKsKrw4= +cloud.google.com/go/dataproc/v2 v2.2.1/go.mod h1:QdAJLaBjh+l4PVlVZcmrmhGccosY/omC1qwfQ61Zv/o= cloud.google.com/go/dataqna v0.7.0/go.mod h1:Lx9OcIIeqCrw1a6KdO3/5KMP1wAmTc0slZWwP12Qq3c= +cloud.google.com/go/dataqna v0.8.2/go.mod h1:KNEqgx8TTmUipnQsScOoDpq/VlXVptUqVMZnt30WAPs= cloud.google.com/go/datastore v1.11.0/go.mod h1:TvGxBIHCS50u8jzG+AW/ppf87v1of8nwzFNgEZU1D3c= +cloud.google.com/go/datastore v1.15.0/go.mod h1:GAeStMBIt9bPS7jMJA85kgkpsMkvseWWXiaHya9Jes8= cloud.google.com/go/datastream v1.7.0/go.mod h1:uxVRMm2elUSPuh65IbZpzJNMbuzkcvu5CjMqVIUHrww= +cloud.google.com/go/datastream v1.10.1/go.mod h1:7ngSYwnw95YFyTd5tOGBxHlOZiL+OtpjheqU7t2/s/c= cloud.google.com/go/deploy v1.8.0/go.mod h1:z3myEJnA/2wnB4sgjqdMfgxCA0EqC3RBTNcVPs93mtQ= +cloud.google.com/go/deploy v1.13.1/go.mod h1:8jeadyLkH9qu9xgO3hVWw8jVr29N1mnW42gRJT8GY6g= cloud.google.com/go/dialogflow v1.32.0/go.mod h1:jG9TRJl8CKrDhMEcvfcfFkkpp8ZhgPz3sBGmAUYJ2qE= +cloud.google.com/go/dialogflow v1.44.1/go.mod h1:n/h+/N2ouKOO+rbe/ZnI186xImpqvCVj2DdsWS/0EAk= cloud.google.com/go/dlp v1.9.0/go.mod h1:qdgmqgTyReTz5/YNSSuueR8pl7hO0o9bQ39ZhtgkWp4= +cloud.google.com/go/dlp v1.10.2/go.mod h1:ZbdKIhcnyhILgccwVDzkwqybthh7+MplGC3kZVZsIOQ= cloud.google.com/go/documentai v1.18.0/go.mod h1:F6CK6iUH8J81FehpskRmhLq/3VlwQvb7TvwOceQ2tbs= +cloud.google.com/go/documentai v1.23.2/go.mod h1:Q/wcRT+qnuXOpjAkvOV4A+IeQl04q2/ReT7SSbytLSo= cloud.google.com/go/domains v0.8.0/go.mod h1:M9i3MMDzGFXsydri9/vW+EWz9sWb4I6WyHqdlAk0idE= +cloud.google.com/go/domains v0.9.2/go.mod h1:3YvXGYzZG1Temjbk7EyGCuGGiXHJwVNmwIf+E/cUp5I= cloud.google.com/go/edgecontainer v1.0.0/go.mod h1:cttArqZpBB2q58W/upSG++ooo6EsblxDIolxa3jSjbY= +cloud.google.com/go/edgecontainer v1.1.2/go.mod h1:wQRjIzqxEs9e9wrtle4hQPSR1Y51kqN75dgF7UllZZ4= cloud.google.com/go/errorreporting v0.3.0/go.mod h1:xsP2yaAp+OAW4OIm60An2bbLpqIhKXdWR/tawvl7QzU= cloud.google.com/go/essentialcontacts v1.5.0/go.mod h1:ay29Z4zODTuwliK7SnX8E86aUF2CTzdNtvv42niCX0M= +cloud.google.com/go/essentialcontacts v1.6.3/go.mod h1:yiPCD7f2TkP82oJEFXFTou8Jl8L6LBRPeBEkTaO0Ggo= cloud.google.com/go/eventarc v1.11.0/go.mod h1:PyUjsUKPWoRBCHeOxZd/lbOOjahV41icXyUY5kSTvVY= +cloud.google.com/go/eventarc v1.13.1/go.mod h1:EqBxmGHFrruIara4FUQ3RHlgfCn7yo1HYsu2Hpt/C3Y= cloud.google.com/go/filestore v1.6.0/go.mod h1:di5unNuss/qfZTw2U9nhFqo8/ZDSc466dre85Kydllg= +cloud.google.com/go/filestore v1.7.2/go.mod h1:TYOlyJs25f/omgj+vY7/tIG/E7BX369triSPzE4LdgE= cloud.google.com/go/firestore v1.9.0/go.mod h1:HMkjKHNTtRyZNiMzu7YAsLr9K3X2udY2AMwDaMEQiiE= +cloud.google.com/go/firestore v1.13.0/go.mod h1:QojqqOh8IntInDUSTAh0c8ZsPYAr68Ma8c5DWOy8xb8= cloud.google.com/go/functions v1.13.0/go.mod h1:EU4O007sQm6Ef/PwRsI8N2umygGqPBS/IZQKBQBcJ3c= +cloud.google.com/go/functions v1.15.2/go.mod h1:CHAjtcR6OU4XF2HuiVeriEdELNcnvRZSk1Q8RMqy4lE= cloud.google.com/go/gaming v1.9.0/go.mod h1:Fc7kEmCObylSWLO334NcO+O9QMDyz+TKC4v1D7X+Bc0= cloud.google.com/go/gkebackup v0.4.0/go.mod h1:byAyBGUwYGEEww7xsbnUTBHIYcOPy/PgUWUtOeRm9Vg= +cloud.google.com/go/gkebackup v1.3.2/go.mod h1:OMZbXzEJloyXMC7gqdSB+EOEQ1AKcpGYvO3s1ec5ixk= cloud.google.com/go/gkeconnect v0.7.0/go.mod h1:SNfmVqPkaEi3bF/B3CNZOAYPYdg7sU+obZ+QTky2Myw= +cloud.google.com/go/gkeconnect v0.8.2/go.mod h1:6nAVhwchBJYgQCXD2pHBFQNiJNyAd/wyxljpaa6ZPrY= cloud.google.com/go/gkehub v0.12.0/go.mod h1:djiIwwzTTBrF5NaXCGv3mf7klpEMcST17VBTVVDcuaw= +cloud.google.com/go/gkehub v0.14.2/go.mod h1:iyjYH23XzAxSdhrbmfoQdePnlMj2EWcvnR+tHdBQsCY= cloud.google.com/go/gkemulticloud v0.5.0/go.mod h1:W0JDkiyi3Tqh0TJr//y19wyb1yf8llHVto2Htf2Ja3Y= +cloud.google.com/go/gkemulticloud v1.0.1/go.mod h1:AcrGoin6VLKT/fwZEYuqvVominLriQBCKmbjtnbMjG8= cloud.google.com/go/gsuiteaddons v1.5.0/go.mod h1:TFCClYLd64Eaa12sFVmUyG62tk4mdIsI7pAnSXRkcFo= +cloud.google.com/go/gsuiteaddons v1.6.2/go.mod h1:K65m9XSgs8hTF3X9nNTPi8IQueljSdYo9F+Mi+s4MyU= cloud.google.com/go/iam v0.13.0/go.mod h1:ljOg+rcNfzZ5d6f1nAUJ8ZIxOaZUVoS14bKCtaLZ/D0= +cloud.google.com/go/iam v1.1.3/go.mod h1:3khUlaBXfPKKe7huYgEpDn6FtgRyMEqbkvBxrQyY5SE= cloud.google.com/go/iap v1.7.1/go.mod h1:WapEwPc7ZxGt2jFGB/C/bm+hP0Y6NXzOYGjpPnmMS74= +cloud.google.com/go/iap v1.9.1/go.mod h1:SIAkY7cGMLohLSdBR25BuIxO+I4fXJiL06IBL7cy/5Q= cloud.google.com/go/ids v1.3.0/go.mod h1:JBdTYwANikFKaDP6LtW5JAi4gubs57SVNQjemdt6xV4= +cloud.google.com/go/ids v1.4.2/go.mod h1:3vw8DX6YddRu9BncxuzMyWn0g8+ooUjI2gslJ7FH3vk= cloud.google.com/go/iot v1.6.0/go.mod h1:IqdAsmE2cTYYNO1Fvjfzo9po179rAtJeVGUvkLN3rLE= +cloud.google.com/go/iot v1.7.2/go.mod h1:q+0P5zr1wRFpw7/MOgDXrG/HVA+l+cSwdObffkrpnSg= cloud.google.com/go/kms v1.10.1/go.mod h1:rIWk/TryCkR59GMC3YtHtXeLzd634lBbKenvyySAyYI= +cloud.google.com/go/kms v1.15.3/go.mod h1:AJdXqHxS2GlPyduM99s9iGqi2nwbviBbhV/hdmt4iOQ= cloud.google.com/go/language v1.9.0/go.mod h1:Ns15WooPM5Ad/5no/0n81yUetis74g3zrbeJBE+ptUY= +cloud.google.com/go/language v1.11.1/go.mod h1:Xyid9MG9WOX3utvDbpX7j3tXDmmDooMyMDqgUVpH17U= cloud.google.com/go/lifesciences v0.8.0/go.mod h1:lFxiEOMqII6XggGbOnKiyZ7IBwoIqA84ClvoezaA/bo= +cloud.google.com/go/lifesciences v0.9.2/go.mod h1:QHEOO4tDzcSAzeJg7s2qwnLM2ji8IRpQl4p6m5Z9yTA= cloud.google.com/go/logging v1.7.0/go.mod h1:3xjP2CjkM3ZkO73aj4ASA5wRPGGCRrPIAeNqVNkzY8M= +cloud.google.com/go/logging v1.8.1/go.mod h1:TJjR+SimHwuC8MZ9cjByQulAMgni+RkXeI3wwctHJEI= cloud.google.com/go/longrunning v0.4.1/go.mod h1:4iWDqhBZ70CvZ6BfETbvam3T8FMvLK+eFj0E6AaRQTo= +cloud.google.com/go/longrunning v0.5.0/go.mod h1:0JNuqRShmscVAhIACGtskSAWtqtOoPkwP0YF1oVEchc= +cloud.google.com/go/longrunning v0.5.2/go.mod h1:nqo6DQbNV2pXhGDbDMoN2bWz68MjZUzqv2YttZiveCs= cloud.google.com/go/managedidentities v1.5.0/go.mod h1:+dWcZ0JlUmpuxpIDfyP5pP5y0bLdRwOS4Lp7gMni/LA= +cloud.google.com/go/managedidentities v1.6.2/go.mod h1:5c2VG66eCa0WIq6IylRk3TBW83l161zkFvCj28X7jn8= cloud.google.com/go/maps v0.7.0/go.mod h1:3GnvVl3cqeSvgMcpRlQidXsPYuDGQ8naBis7MVzpXsY= +cloud.google.com/go/maps v1.4.1/go.mod h1:BxSa0BnW1g2U2gNdbq5zikLlHUuHW0GFWh7sgML2kIY= cloud.google.com/go/mediatranslation v0.7.0/go.mod h1:LCnB/gZr90ONOIQLgSXagp8XUW1ODs2UmUMvcgMfI2I= +cloud.google.com/go/mediatranslation v0.8.2/go.mod h1:c9pUaDRLkgHRx3irYE5ZC8tfXGrMYwNZdmDqKMSfFp8= cloud.google.com/go/memcache v1.9.0/go.mod h1:8oEyzXCu+zo9RzlEaEjHl4KkgjlNDaXbCQeQWlzNFJM= +cloud.google.com/go/memcache v1.10.2/go.mod h1:f9ZzJHLBrmd4BkguIAa/l/Vle6uTHzHokdnzSWOdQ6A= cloud.google.com/go/metastore v1.10.0/go.mod h1:fPEnH3g4JJAk+gMRnrAnoqyv2lpUCqJPWOodSaf45Eo= +cloud.google.com/go/metastore v1.13.1/go.mod h1:IbF62JLxuZmhItCppcIfzBBfUFq0DIB9HPDoLgWrVOU= cloud.google.com/go/monitoring v1.13.0/go.mod h1:k2yMBAB1H9JT/QETjNkgdCGD9bPF712XiLTVr+cBrpw= +cloud.google.com/go/monitoring v1.16.1/go.mod h1:6HsxddR+3y9j+o/cMJH6q/KJ/CBTvM/38L/1m7bTRJ4= cloud.google.com/go/networkconnectivity v1.11.0/go.mod h1:iWmDD4QF16VCDLXUqvyspJjIEtBR/4zq5hwnY2X3scM= +cloud.google.com/go/networkconnectivity v1.14.1/go.mod h1:LyGPXR742uQcDxZ/wv4EI0Vu5N6NKJ77ZYVnDe69Zug= cloud.google.com/go/networkmanagement v1.6.0/go.mod h1:5pKPqyXjB/sgtvB5xqOemumoQNB7y95Q7S+4rjSOPYY= +cloud.google.com/go/networkmanagement v1.9.1/go.mod h1:CCSYgrQQvW73EJawO2QamemYcOb57LvrDdDU51F0mcI= cloud.google.com/go/networksecurity v0.8.0/go.mod h1:B78DkqsxFG5zRSVuwYFRZ9Xz8IcQ5iECsNrPn74hKHU= +cloud.google.com/go/networksecurity v0.9.2/go.mod h1:jG0SeAttWzPMUILEHDUvFYdQTl8L/E/KC8iZDj85lEI= cloud.google.com/go/notebooks v1.8.0/go.mod h1:Lq6dYKOYOWUCTvw5t2q1gp1lAp0zxAxRycayS0iJcqQ= +cloud.google.com/go/notebooks v1.10.1/go.mod h1:5PdJc2SgAybE76kFQCWrTfJolCOUQXF97e+gteUUA6A= cloud.google.com/go/optimization v1.3.1/go.mod h1:IvUSefKiwd1a5p0RgHDbWCIbDFgKuEdB+fPPuP0IDLI= +cloud.google.com/go/optimization v1.5.1/go.mod h1:NC0gnUD5MWVAF7XLdoYVPmYYVth93Q6BUzqAq3ZwtV8= cloud.google.com/go/orchestration v1.6.0/go.mod h1:M62Bevp7pkxStDfFfTuCOaXgaaqRAga1yKyoMtEoWPQ= +cloud.google.com/go/orchestration v1.8.2/go.mod h1:T1cP+6WyTmh6LSZzeUhvGf0uZVmJyTx7t8z7Vg87+A0= cloud.google.com/go/orgpolicy v1.10.0/go.mod h1:w1fo8b7rRqlXlIJbVhOMPrwVljyuW5mqssvBtU18ONc= +cloud.google.com/go/orgpolicy v1.11.2/go.mod h1:biRDpNwfyytYnmCRWZWxrKF22Nkz9eNVj9zyaBdpm1o= cloud.google.com/go/osconfig v1.11.0/go.mod h1:aDICxrur2ogRd9zY5ytBLV89KEgT2MKB2L/n6x1ooPw= +cloud.google.com/go/osconfig v1.12.2/go.mod h1:eh9GPaMZpI6mEJEuhEjUJmaxvQ3gav+fFEJon1Y8Iw0= cloud.google.com/go/oslogin v1.9.0/go.mod h1:HNavntnH8nzrn8JCTT5fj18FuJLFJc4NaZJtBnQtKFs= +cloud.google.com/go/oslogin v1.11.1/go.mod h1:OhD2icArCVNUxKqtK0mcSmKL7lgr0LVlQz+v9s1ujTg= cloud.google.com/go/phishingprotection v0.7.0/go.mod h1:8qJI4QKHoda/sb/7/YmMQ2omRLSLYSu9bU0EKCNI+Lk= +cloud.google.com/go/phishingprotection v0.8.2/go.mod h1:LhJ91uyVHEYKSKcMGhOa14zMMWfbEdxG032oT6ECbC8= cloud.google.com/go/policytroubleshooter v1.6.0/go.mod h1:zYqaPTsmfvpjm5ULxAyD/lINQxJ0DDsnWOP/GZ7xzBc= +cloud.google.com/go/policytroubleshooter v1.9.1/go.mod h1:MYI8i0bCrL8cW+VHN1PoiBTyNZTstCg2WUw2eVC4c4U= cloud.google.com/go/privatecatalog v0.8.0/go.mod h1:nQ6pfaegeDAq/Q5lrfCQzQLhubPiZhSaNhIgfJlnIXs= +cloud.google.com/go/privatecatalog v0.9.2/go.mod h1:RMA4ATa8IXfzvjrhhK8J6H4wwcztab+oZph3c6WmtFc= cloud.google.com/go/pubsub v1.30.0/go.mod h1:qWi1OPS0B+b5L+Sg6Gmc9zD1Y+HaM0MdUr7LsupY1P4= +cloud.google.com/go/pubsub v1.33.0/go.mod h1:f+w71I33OMyxf9VpMVcZbnG5KSUkCOUHYpFd5U1GdRc= cloud.google.com/go/pubsublite v1.7.0/go.mod h1:8hVMwRXfDfvGm3fahVbtDbiLePT3gpoiJYJY+vxWxVM= +cloud.google.com/go/pubsublite v1.8.1/go.mod h1:fOLdU4f5xldK4RGJrBMm+J7zMWNj/k4PxwEZXy39QS0= cloud.google.com/go/recaptchaenterprise/v2 v2.7.0/go.mod h1:19wVj/fs5RtYtynAPJdDTb69oW0vNHYDBTbB4NvMD9c= +cloud.google.com/go/recaptchaenterprise/v2 v2.8.1/go.mod h1:JZYZJOeZjgSSTGP4uz7NlQ4/d1w5hGmksVgM0lbEij0= cloud.google.com/go/recommendationengine v0.7.0/go.mod h1:1reUcE3GIu6MeBz/h5xZJqNLuuVjNg1lmWMPyjatzac= +cloud.google.com/go/recommendationengine v0.8.2/go.mod h1:QIybYHPK58qir9CV2ix/re/M//Ty10OxjnnhWdaKS1Y= cloud.google.com/go/recommender v1.9.0/go.mod h1:PnSsnZY7q+VL1uax2JWkt/UegHssxjUVVCrX52CuEmQ= +cloud.google.com/go/recommender v1.11.1/go.mod h1:sGwFFAyI57v2Hc5LbIj+lTwXipGu9NW015rkaEM5B18= cloud.google.com/go/redis v1.11.0/go.mod h1:/X6eicana+BWcUda5PpwZC48o37SiFVTFSs0fWAJ7uQ= +cloud.google.com/go/redis v1.13.2/go.mod h1:0Hg7pCMXS9uz02q+LoEVl5dNHUkIQv+C/3L76fandSA= cloud.google.com/go/resourcemanager v1.7.0/go.mod h1:HlD3m6+bwhzj9XCouqmeiGuni95NTrExfhoSrkC/3EI= +cloud.google.com/go/resourcemanager v1.9.2/go.mod h1:OujkBg1UZg5lX2yIyMo5Vz9O5hf7XQOSV7WxqxxMtQE= cloud.google.com/go/resourcesettings v1.5.0/go.mod h1:+xJF7QSG6undsQDfsCJyqWXyBwUoJLhetkRMDRnIoXA= +cloud.google.com/go/resourcesettings v1.6.2/go.mod h1:mJIEDd9MobzunWMeniaMp6tzg4I2GvD3TTmPkc8vBXk= cloud.google.com/go/retail v1.12.0/go.mod h1:UMkelN/0Z8XvKymXFbD4EhFJlYKRx1FGhQkVPU5kF14= +cloud.google.com/go/retail v1.14.2/go.mod h1:W7rrNRChAEChX336QF7bnMxbsjugcOCPU44i5kbLiL8= cloud.google.com/go/run v0.9.0/go.mod h1:Wwu+/vvg8Y+JUApMwEDfVfhetv30hCG4ZwDR/IXl2Qg= +cloud.google.com/go/run v1.3.1/go.mod h1:cymddtZOzdwLIAsmS6s+Asl4JoXIDm/K1cpZTxV4Q5s= cloud.google.com/go/scheduler v1.9.0/go.mod h1:yexg5t+KSmqu+njTIh3b7oYPheFtBWGcbVUYF1GGMIc= +cloud.google.com/go/scheduler v1.10.2/go.mod h1:O3jX6HRH5eKCA3FutMw375XHZJudNIKVonSCHv7ropY= cloud.google.com/go/secretmanager v1.10.0/go.mod h1:MfnrdvKMPNra9aZtQFvBcvRU54hbPD8/HayQdlUgJpU= +cloud.google.com/go/secretmanager v1.11.2/go.mod h1:MQm4t3deoSub7+WNwiC4/tRYgDBHJgJPvswqQVB1Vss= cloud.google.com/go/security v1.13.0/go.mod h1:Q1Nvxl1PAgmeW0y3HTt54JYIvUdtcpYKVfIB8AOMZ+0= +cloud.google.com/go/security v1.15.2/go.mod h1:2GVE/v1oixIRHDaClVbHuPcZwAqFM28mXuAKCfMgYIg= cloud.google.com/go/securitycenter v1.19.0/go.mod h1:LVLmSg8ZkkyaNy4u7HCIshAngSQ8EcIRREP3xBnyfag= +cloud.google.com/go/securitycenter v1.23.1/go.mod h1:w2HV3Mv/yKhbXKwOCu2i8bCuLtNP1IMHuiYQn4HJq5s= cloud.google.com/go/servicedirectory v1.9.0/go.mod h1:29je5JjiygNYlmsGz8k6o+OZ8vd4f//bQLtvzkPPT/s= +cloud.google.com/go/servicedirectory v1.11.1/go.mod h1:tJywXimEWzNzw9FvtNjsQxxJ3/41jseeILgwU/QLrGI= cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+qE2f9A= +cloud.google.com/go/shell v1.7.2/go.mod h1:KqRPKwBV0UyLickMn0+BY1qIyE98kKyI216sH/TuHmc= cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= +cloud.google.com/go/spanner v1.50.0/go.mod h1:eGj9mQGK8+hkgSVbHNQ06pQ4oS+cyc4tXXd6Dif1KoM= cloud.google.com/go/speech v1.15.0/go.mod h1:y6oH7GhqCaZANH7+Oe0BhgIogsNInLlz542tg3VqeYI= +cloud.google.com/go/speech v1.19.1/go.mod h1:WcuaWz/3hOlzPFOVo9DUsblMIHwxP589y6ZMtaG+iAA= +cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= cloud.google.com/go/storagetransfer v1.8.0/go.mod h1:JpegsHHU1eXg7lMHkvf+KE5XDJ7EQu0GwNJbbVGanEw= +cloud.google.com/go/storagetransfer v1.10.1/go.mod h1:rS7Sy0BtPviWYTTJVWCSV4QrbBitgPeuK4/FKa4IdLs= cloud.google.com/go/talent v1.5.0/go.mod h1:G+ODMj9bsasAEJkQSzO2uHQWXHHXUomArjWQQYkqK6c= +cloud.google.com/go/talent v1.6.3/go.mod h1:xoDO97Qd4AK43rGjJvyBHMskiEf3KulgYzcH6YWOVoo= cloud.google.com/go/texttospeech v1.6.0/go.mod h1:YmwmFT8pj1aBblQOI3TfKmwibnsfvhIBzPXcW4EBovc= +cloud.google.com/go/texttospeech v1.7.2/go.mod h1:VYPT6aTOEl3herQjFHYErTlSZJ4vB00Q2ZTmuVgluD4= cloud.google.com/go/tpu v1.5.0/go.mod h1:8zVo1rYDFuW2l4yZVY0R0fb/v44xLh3llq7RuV61fPM= +cloud.google.com/go/tpu v1.6.2/go.mod h1:NXh3NDwt71TsPZdtGWgAG5ThDfGd32X1mJ2cMaRlVgU= cloud.google.com/go/trace v1.9.0/go.mod h1:lOQqpE5IaWY0Ixg7/r2SjixMuc6lfTFeO4QGM4dQWOk= +cloud.google.com/go/trace v1.10.2/go.mod h1:NPXemMi6MToRFcSxRl2uDnu/qAlAQ3oULUphcHGh1vA= cloud.google.com/go/translate v1.7.0/go.mod h1:lMGRudH1pu7I3n3PETiOB2507gf3HnfLV8qlkHZEyos= +cloud.google.com/go/translate v1.9.1/go.mod h1:TWIgDZknq2+JD4iRcojgeDtqGEp154HN/uL6hMvylS8= cloud.google.com/go/video v1.15.0/go.mod h1:SkgaXwT+lIIAKqWAJfktHT/RbgjSuY6DobxEp0C5yTQ= +cloud.google.com/go/video v1.20.1/go.mod h1:3gJS+iDprnj8SY6pe0SwLeC5BUW80NjhwX7INWEuWGU= cloud.google.com/go/videointelligence v1.10.0/go.mod h1:LHZngX1liVtUhZvi2uNS0VQuOzNi2TkY1OakiuoUOjU= +cloud.google.com/go/videointelligence v1.11.2/go.mod h1:ocfIGYtIVmIcWk1DsSGOoDiXca4vaZQII1C85qtoplc= cloud.google.com/go/vision/v2 v2.7.0/go.mod h1:H89VysHy21avemp6xcf9b9JvZHVehWbET0uT/bcuY/0= +cloud.google.com/go/vision/v2 v2.7.3/go.mod h1:V0IcLCY7W+hpMKXK1JYE0LV5llEqVmj+UJChjvA1WsM= cloud.google.com/go/vmmigration v1.6.0/go.mod h1:bopQ/g4z+8qXzichC7GW1w2MjbErL54rk3/C843CjfY= +cloud.google.com/go/vmmigration v1.7.2/go.mod h1:iA2hVj22sm2LLYXGPT1pB63mXHhrH1m/ruux9TwWLd8= cloud.google.com/go/vmwareengine v0.3.0/go.mod h1:wvoyMvNWdIzxMYSpH/R7y2h5h3WFkx6d+1TIsP39WGY= +cloud.google.com/go/vmwareengine v1.0.1/go.mod h1:aT3Xsm5sNx0QShk1Jc1B8OddrxAScYLwzVoaiXfdzzk= cloud.google.com/go/vpcaccess v1.6.0/go.mod h1:wX2ILaNhe7TlVa4vC5xce1bCnqE3AeH27RV31lnmZes= +cloud.google.com/go/vpcaccess v1.7.2/go.mod h1:mmg/MnRHv+3e8FJUjeSibVFvQF1cCy2MsFaFqxeY1HU= cloud.google.com/go/webrisk v1.8.0/go.mod h1:oJPDuamzHXgUc+b8SiHRcVInZQuybnvEW72PqTc7sSg= +cloud.google.com/go/webrisk v1.9.2/go.mod h1:pY9kfDgAqxUpDBOrG4w8deLfhvJmejKB0qd/5uQIPBc= cloud.google.com/go/websecurityscanner v1.5.0/go.mod h1:Y6xdCPy81yi0SQnDY1xdNTNpfY1oAgXUlcfN3B3eSng= +cloud.google.com/go/websecurityscanner v1.6.2/go.mod h1:7YgjuU5tun7Eg2kpKgGnDuEOXWIrh8x8lWrJT4zfmas= cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw= +cloud.google.com/go/workflows v1.12.1/go.mod h1:5A95OhD/edtOhQd/O741NSfIMezNTbCwLM1P1tBRGHM= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/alecthomas/kingpin/v2 v2.3.2 h1:H0aULhgmSzN8xQ3nX1uxtdlTHYoPLu5AhHxWrKI6ocU= github.com/alecthomas/kingpin/v2 v2.3.2/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc= github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE= github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMrBo8f1j86j5WHzznCCQxV/b8g= github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk= github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= +github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -149,23 +281,69 @@ github.com/dave/patsy v0.0.0-20210517141501-957256f50cba h1:1o36L4EKbZzazMk8iGC4 github.com/dave/patsy v0.0.0-20210517141501-957256f50cba/go.mod h1:qfR88CgEGLoiqDaE+xxDCi5QA5v4vUoW0UCX2Nd5Tlc= github.com/dave/rebecca v0.9.1 h1:jxVfdOxRirbXL28vXMvUvJ1in3djwkVKXCq339qhBL0= github.com/dave/rebecca v0.9.1/go.mod h1:N6XYdMD/OKw3lkF3ywh8Z6wPGuwNFDNtWYEMFWEmXBA= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f h1:7T++XKzy4xg7PKy+bM+Sa9/oe1OC88yz2hXQUISoXfA= github.com/envoyproxy/go-control-plane v0.11.1-0.20230524094728-9239064ad72f/go.mod h1:sfYdkwUW4BA3PbKjySwjJy+O4Pu0h62rlqCMHNk+K+Q= +github.com/envoyproxy/go-control-plane v0.11.1/go.mod h1:uhMcXKCQMEJHiAb0w+YGefQLaTEw+YhGluxZkrTmD0g= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8= github.com/envoyproxy/protoc-gen-validate v0.10.1/go.mod h1:DRjgyB0I43LtJapqN6NiRwroiAU2PaFuvk/vjgh61ss= +github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.1.0/go.mod h1:pfYeQZ3JWZoXTV5sFc986z3HTpwQs9At6P4ImfuP3NQ= +github.com/golang/glog v1.1.2/go.mod h1:zR+okUeTbrL6EL3xHUDxZuEtGv04p5shwip1+mL/rLQ= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-pkcs11 v0.2.0/go.mod h1:6eQoGcuNJpa7jnd5pMGdkSaQpNDYvPlXWMcjXXThLlY= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A= +github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.4/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= github.com/googleapis/gax-go/v2 v2.7.1/go.mod h1:4orTrqY6hXxxaUL4LHIPl6lGo8vAE38/qKbhSAKP6QI= +github.com/googleapis/gax-go/v2 v2.11.0/go.mod h1:DxmR61SGKkGLa2xigwuZIQpkCI2S5iydzRfb3peWZJI= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -174,7 +352,10 @@ github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4d github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= @@ -184,6 +365,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30 h1:BHT1/DKsYDGkUgQ2jmMaozVcdk+sVfz0+1ZJq4zkWgw= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/prometheus/client_golang v1.15.1/go.mod h1:e9yaBhRPU2pPNsZwE+JdQl0KEt1N9XgF6zxWmaC0xOk= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.4.1-0.20230718164431-9a2bf3000d16/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY= github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= @@ -195,6 +378,9 @@ github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNX github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= @@ -205,48 +391,170 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.17.0 h1:eU0ffpYuEY7eQ75K+nKr9CI5KcY8h+GPk/9DDlEO1NI= go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.17.0/go.mod h1:9P5RK5JS2sjKepuCkqFwPp3etwV/57E0eigLw18Mn1k= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= +golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= +golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220907140024-f12130a52804/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= +google.golang.org/api v0.126.0/go.mod h1:mBwVAtz+87bEN6CbA1GtZPDOqY2R5ONPqJeIlvyo4Aw= +google.golang.org/api v0.128.0/go.mod h1:Y611qgqaE92On/7g65MQgxYul3c0rEB894kniWLY750= +google.golang.org/api v0.139.0/go.mod h1:CVagp6Eekz9CjGZ718Z+sloknzkDJE7Vc1Ckj9+viBk= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20230323212658-478b75c54725/go.mod h1:UUQDJDOlWu4KYeJZffbWgBkS1YFobzKbLVfK69pe0Ak= google.golang.org/genproto v0.0.0-20230525234025-438c736192d0/go.mod h1:9ExIQyXL5hZrHzQceCwuSYwZZ5QZBazOcprJ5rgs3lY= google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= +google.golang.org/genproto v0.0.0-20230530153820-e85fd2cbaebc/go.mod h1:xZnkP7mREFX5MORlOPEzLMr+90PPZQ2QWzrVTWfAq64= +google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8= +google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:CgAqfJo+Xmu0GwA0411Ht3OU3OntXwsGmrmjI8ioGXI= google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9/go.mod h1:vHYtlOoi6TsQ3Uk2yxR7NI5z8uoV+3pZtR4jmHIkRig= +google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ= +google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q= +google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/api v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:SUBoKXbI1Efip18FClrQVGjWcyd0QZd8KkvdP34t7ww= +google.golang.org/genproto/googleapis/bytestream v0.0.0-20230807174057-1744710a1577/go.mod h1:NjCQG/D8JandXxM57PZbAJL1DCNL6EypA0vPPwfsc7c= google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231012201019-e917dd12ba7a/go.mod h1:4cYg8o5yUbm77w8ZX00LhMVNl/YVBFJRYWDc0uYWMs0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b/go.mod h1:swOH3j0KzcDDgGUWr+SNpyTen5YrXjS3eyPzFYKc6lc= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8= +google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= +google.golang.org/grpc v1.58.0/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/autometrics/ctx.go b/internal/autometrics/ctx.go index d157c82..1b50b88 100644 --- a/internal/autometrics/ctx.go +++ b/internal/autometrics/ctx.go @@ -47,8 +47,11 @@ type GeneratorContext struct { // only statically-known information is useful at this point. type RuntimeCtxInfo struct { // Name of the variable to use as context.Context when building the autometrics.Context. - // The string will be empty if and only if 'nil' must be used as autometrics.NewContext() argument. + // The string will be empty if 'nil' must be used as autometrics.NewContext() argument. ContextVariableName string + // Name of the variable to assign to the context returned by autometrics.PreInstrument + // The string will be empty if a new variable must be used as autometrics.PreInstrument() return value assignment. + NewContextVariableName string // Verbatim code to use to fetch the TraceID. // For example, if the instrumented function is detected to use Gin, like // `func ginHandler(ginVarName *gin.Context)` @@ -65,9 +68,10 @@ type RuntimeCtxInfo struct { func DefaultRuntimeCtxInfo() RuntimeCtxInfo { return RuntimeCtxInfo{ - TrackConcurrentCalls: true, - TrackCallerName: true, - ContextVariableName: "nil", + TrackConcurrentCalls: true, + TrackCallerName: true, + ContextVariableName: "nil", + NewContextVariableName: "", } } @@ -164,7 +168,7 @@ func NewGeneratorContext(implementation autometrics.Implementation, prometheusUr if prometheusUrl != "" { promUrl, err := url.Parse(prometheusUrl) if err != nil { - return ctx, fmt.Errorf("failed to parse prometheus URL: %w", err) + return ctx, fmt.Errorf("parsing prometheus URL: %w", err) } ctx.DocumentationGenerator = NewPrometheusDoc(*promUrl) diff --git a/internal/build/build.go b/internal/build/build.go index 3600686..6170b83 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -2,3 +2,9 @@ package build // import "github.com/autometrics-dev/autometrics-go/internal/buil // Version is the version string of the build, when made available through ldflags. var Version = "development" + +// User is the user who triggered this build, when made available through ldflags. +var User = "n/a" + +// Time is the timestamp string of the build, when made available through ldflags. +var Time = "n/a" diff --git a/internal/generate/context.go b/internal/generate/context.go new file mode 100644 index 0000000..1d220be --- /dev/null +++ b/internal/generate/context.go @@ -0,0 +1,379 @@ +package generate // import "github.com/autometrics-dev/autometrics-go/internal/generate" + +import ( + "fmt" + "go/token" + "log" + "reflect" + "strings" + + "golang.org/x/exp/slices" + + internal "github.com/autometrics-dev/autometrics-go/internal/autometrics" + am "github.com/autometrics-dev/autometrics-go/pkg/autometrics" + + "github.com/dave/dst" + "github.com/dave/dst/decorator" +) + +const ( + vanillaContext = "context" + gin = "github.com/gin-gonic/gin" + buffalo = "github.com/gobuffalo/buffalo" + echoV4 = "github.com/labstack/echo/v4" + netHttp = "net/http" + amDefaultContextName = "amCtx" + contextDecoration = "//autometrics:shadow-ctx" +) + +// injectContextStatement add all the necessary information into context to produce the correct context shadowing statement. +func injectContextStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) (identName string, err error) { + err = detectContext(ctx, funcDeclaration) + if err != nil { + return "", fmt.Errorf("getting context for tracing: %w", err) + } + + autometricsContextStatement, err := buildAutometricsContextStatement(ctx) + if err != nil { + return "", fmt.Errorf("building the defer statement for instrumentation: %w", err) + } + + funcDeclaration.Body.List = append([]dst.Stmt{&autometricsContextStatement}, funcDeclaration.Body.List...) + + // The hard cast is okay here because we just built ourselves the statement. + return autometricsContextStatement.Lhs[0].(*dst.Ident).Name, nil +} + +// removeContextStatement removes, if detected, a previously injected context shadowing statement. +func removeContextStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) error { + for index, statement := range funcDeclaration.Body.List { + if assignStatement, ok := statement.(*dst.AssignStmt); ok { + decorations := assignStatement.Decorations().End + if slices.Contains(decorations.All(), contextDecoration) { + funcDeclaration.Body.List = append(funcDeclaration.Body.List[:index], funcDeclaration.Body.List[index+1:]...) + return nil + } + } + } + return nil +} + +// findContextStatement finds a previously injected context shadowing statement. +// It also updates the passed context so that the ContextVariableName is accurate. +func findContextStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) (index int, found bool) { + for index, statement := range funcDeclaration.Body.List { + if assignStatement, ok := statement.(*dst.AssignStmt); ok { + decorations := assignStatement.Decorations().End + if slices.Contains(decorations.All(), contextDecoration) { + ctx.RuntimeCtx.ContextVariableName = assignStatement.Lhs[0].(*dst.Ident).Name + return index, true + } + } + } + return 0, false +} + +// buildAutometricsContextStatement builds the AST node for the context shadowing instrumentation statement to be inserted. +func buildAutometricsContextStatement(ctx *internal.GeneratorContext) (dst.AssignStmt, error) { + preInstrumentArg, contextShadowName, err := buildAutometricsContextNode(ctx) + if err != nil { + return dst.AssignStmt{}, fmt.Errorf("could not generate the runtime context value: %w", err) + } + + // Crude detection of "should the assignment be `:=` or `=`" + assignmentToken := token.ASSIGN + if contextShadowName == amDefaultContextName { + assignmentToken = token.DEFINE + } + + // TODO: deal with cases where the context variable name does not exist. + statement := dst.AssignStmt{ + Lhs: []dst.Expr{ + dst.NewIdent(contextShadowName), + }, + Tok: assignmentToken, + Rhs: []dst.Expr{ + &dst.CallExpr{ + Fun: dst.NewIdent(fmt.Sprintf("%vPreInstrument", autometricsNamespacePrefix(ctx))), + Args: []dst.Expr{ + preInstrumentArg, + }, + }, + }, + } + + statement.Decs.Before = dst.NewLine + statement.Decs.End = []string{contextDecoration} + statement.Decs.After = dst.NewLine + + return statement, nil +} + +// buildAutometricsContextNode creates an AST node representing the runtime context to inject in the instrumented code. +// +// This AST node is later used to create the defer statement responsible for instrumenting the code. +func buildAutometricsContextNode(agc *internal.GeneratorContext) (newContextCall *dst.CallExpr, contextShadowName string, err error) { + // Using https://github.com/dave/dst/issues/73 workaround + + var options []string + + if agc.RuntimeCtx.TraceIDGetter != "" { + options = append(options, fmt.Sprintf("%vWithTraceID(%v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.TraceIDGetter)) + } + if agc.RuntimeCtx.SpanIDGetter != "" { + options = append(options, fmt.Sprintf("%vWithSpanID(%v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.SpanIDGetter)) + } + + options = append(options, + fmt.Sprintf("%vWithConcurrentCalls(%#v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.TrackConcurrentCalls), + fmt.Sprintf("%vWithCallerName(%#v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.TrackCallerName), + ) + + if agc.RuntimeCtx.AlertConf != nil { + options = append(options, fmt.Sprintf("%vWithSloName(%#v)", + autometricsNamespacePrefix(agc), + agc.RuntimeCtx.AlertConf.ServiceName, + )) + if agc.RuntimeCtx.AlertConf.Latency != nil { + options = append(options, fmt.Sprintf("%vWithAlertLatency(%#v * time.Nanosecond, %#v)", + autometricsNamespacePrefix(agc), + agc.RuntimeCtx.AlertConf.Latency.Target, + agc.RuntimeCtx.AlertConf.Latency.Objective, + )) + } + if agc.RuntimeCtx.AlertConf.Success != nil { + options = append(options, fmt.Sprintf("%vWithAlertSuccess(%#v)", + autometricsNamespacePrefix(agc), + agc.RuntimeCtx.AlertConf.Success.Objective)) + } + } + + contextShadowName = agc.RuntimeCtx.NewContextVariableName + if contextShadowName == "nil" || contextShadowName == "" { + contextShadowName = amDefaultContextName + } + + var buf strings.Builder + _, err = fmt.Fprintf( + &buf, + ` +package main + +var dummy = %vNewContext( + %s, +`, + autometricsNamespacePrefix(agc), + agc.RuntimeCtx.ContextVariableName, + ) + if err != nil { + return nil, contextShadowName, fmt.Errorf("could not write string builder to build dummy source code: %w", err) + } + + for _, o := range options { + _, err = fmt.Fprintf(&buf, "\t%s,\n", o) + if err != nil { + return nil, contextShadowName, fmt.Errorf("could not write string builder to build dummy source code: %w", err) + } + } + + _, err = fmt.Fprint(&buf, ")\n") + if err != nil { + return nil, contextShadowName, fmt.Errorf("could not write string builder to build dummy source code: %w", err) + } + + sourceCode := buf.String() + sourceAst, err := decorator.Parse(sourceCode) + if err != nil { + return nil, contextShadowName, fmt.Errorf( + "could not parse dummy code\n%s\n: %w", + sourceCode, + err, + ) + } + + genDeclNode, ok := sourceAst.Decls[0].(*dst.GenDecl) + if !ok { + return nil, contextShadowName, fmt.Errorf("unexpected node in the dummy code (expected dst.GenDecl): %w", err) + } + + specNode, ok := genDeclNode.Specs[0].(*dst.ValueSpec) + if !ok { + return nil, contextShadowName, fmt.Errorf("unexpected node in the dummy code (expected dst.ValueSpec): %w", err) + } + + callExpr, ok := specNode.Values[0].(*dst.CallExpr) + if !ok { + return nil, contextShadowName, fmt.Errorf("unexpected node in the dummy code (expected dst.CallExpr): %w", err) + } + + return callExpr, contextShadowName, nil +} + +// detectContextIdentImpl is a Context detection logic helper for arguments whose type is an identifier +// +// The function returns true when it found enough information to ask for iteration to stop. +func detectContextIdentImpl(ctx *internal.GeneratorContext, argName string, ident *dst.Ident) (bool, error) { + typeName := ident.Name + // If argType is just a dst.Ident when parsing, that means + // it is a single identifier ('Context', _not_ 'context.Context'). + // Therefore we can solely check imports that got imported as '.' + for alias, canonical := range ctx.ImportsMap { + if alias != "." { + continue + } + + if canonical == vanillaContext && typeName == "Context" { + ctx.RuntimeCtx.ContextVariableName = argName + ctx.RuntimeCtx.NewContextVariableName = argName + ctx.RuntimeCtx.SpanIDGetter = "" + ctx.RuntimeCtx.TraceIDGetter = "" + return true, nil + } + + if canonical == netHttp && typeName == "Request" { + if argName == "_" { + log.Println("Warning: an unnamed net/http.Request has been detected. To make Autometrics reuse its context for tracing purposes, please name it, and run 'go generate' again") + ctx.RuntimeCtx.ContextVariableName = "nil" + } else { + ctx.RuntimeCtx.ContextVariableName = fmt.Sprintf("%s.Context()", argName) + } + ctx.RuntimeCtx.NewContextVariableName = "" + ctx.RuntimeCtx.SpanIDGetter = "" + ctx.RuntimeCtx.TraceIDGetter = "" + return true, nil + } + + if canonical == gin && typeName == "Context" { + ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) + ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) + return true, nil + } + + // Buffalo context embeds a context.Context so it can work like vanilla + if canonical == buffalo && typeName == "Context" { + ctx.RuntimeCtx.ContextVariableName = argName + ctx.RuntimeCtx.NewContextVariableName = argName + ctx.RuntimeCtx.SpanIDGetter = "" + ctx.RuntimeCtx.TraceIDGetter = "" + return true, nil + } + + if canonical == echoV4 && typeName == "Context" { + ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) + ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) + return true, nil + } + } + + return false, nil +} + +// detectContextIdentImpl is a Context detection logic helper for arguments whose type is a selector expression. +// +// The function returns true when it found enough information to ask for iteration to stop. +func detectContextSelectorImpl(ctx *internal.GeneratorContext, argName string, selector *dst.SelectorExpr) (bool, error) { + typeName := selector.Sel.Name + if parent, p_ok := selector.X.(*dst.Ident); p_ok { + parentName := parent.Name + for alias, canonical := range ctx.ImportsMap { + if canonical == vanillaContext && parentName == alias && typeName == "Context" { + ctx.RuntimeCtx.ContextVariableName = argName + ctx.RuntimeCtx.NewContextVariableName = argName + ctx.RuntimeCtx.SpanIDGetter = "" + ctx.RuntimeCtx.TraceIDGetter = "" + return true, nil + } + + if canonical == netHttp && parentName == alias && typeName == "Request" { + ctx.RuntimeCtx.ContextVariableName = fmt.Sprintf("%s.Context()", argName) + if argName == "_" { + log.Println("Warning: an unnamed net/http.Request has been detected. To make Autometrics reuse its context for tracing purposes, please name it, and run 'go generate' again") + ctx.RuntimeCtx.ContextVariableName = "nil" + } else { + ctx.RuntimeCtx.ContextVariableName = fmt.Sprintf("%s.Context()", argName) + } + ctx.RuntimeCtx.NewContextVariableName = "" + ctx.RuntimeCtx.SpanIDGetter = "" + ctx.RuntimeCtx.TraceIDGetter = "" + return true, nil + } + + if canonical == gin && parentName == alias && typeName == "Context" { + ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) + ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) + return true, nil + } + + // Buffalo context embeds a context.Context so it can work like vanilla + if canonical == buffalo && parentName == alias && typeName == "Context" { + ctx.RuntimeCtx.ContextVariableName = argName + ctx.RuntimeCtx.NewContextVariableName = argName + ctx.RuntimeCtx.SpanIDGetter = "" + ctx.RuntimeCtx.TraceIDGetter = "" + return true, nil + } + + if canonical == echoV4 && typeName == "Context" && (parentName == alias || parentName == "echo") { + ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) + ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) + return true, nil + } + } + } else { + // TODO: log that autometrics cannot detect multi-nested contexts instead of errorring + // continue + return true, fmt.Errorf("expecting parent to be an identifier, got %s instead", reflect.TypeOf(selector.X).String()) + } + return false, nil +} + +// detectContext modifies a RuntimeCtxInfo to inject context when detected in the function signature. +func detectContext(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) error { + arguments := funcDeclaration.Type.Params.List + for _, argGroup := range arguments { + if len(argGroup.Names) > 1 { + continue + } + argName := argGroup.Names[0].Name + if argGroup.Type == nil { + continue + } + + if argType, ok := argGroup.Type.(*dst.Ident); ok { + if found, err := detectContextIdentImpl(ctx, argName, argType); found { + return err + } + } else if argType, ok := argGroup.Type.(*dst.SelectorExpr); ok { + if found, err := detectContextSelectorImpl(ctx, argName, argType); found { + return err + } + } else if argType, ok := argGroup.Type.(*dst.StarExpr); ok { + if ident, ok := argType.X.(*dst.Ident); ok { + if found, err := detectContextIdentImpl(ctx, argName, ident); found { + return err + } + } else if selector, ok := argType.X.(*dst.SelectorExpr); ok { + if found, err := detectContextSelectorImpl(ctx, argName, selector); found { + return err + } + } else { + log.Printf("the type being pointed to by argument %s in %s is %s, skipping...", + argName, + funcDeclaration.Name.Name, + reflect.TypeOf(argType.X).String(), + ) + continue + } + } else { + log.Printf("the type of argument %s in %s is %s, skipping...", + argName, + funcDeclaration.Name.Name, + reflect.TypeOf(argGroup.Type).String(), + ) + continue + } + } + + ctx.RuntimeCtx.ContextVariableName = "nil" + return nil +} diff --git a/internal/generate/defer.go b/internal/generate/defer.go index 1559f82..7f71d17 100644 --- a/internal/generate/defer.go +++ b/internal/generate/defer.go @@ -2,37 +2,31 @@ package generate // import "github.com/autometrics-dev/autometrics-go/internal/g import ( "fmt" - "log" - "reflect" - "strings" "golang.org/x/exp/slices" internal "github.com/autometrics-dev/autometrics-go/internal/autometrics" - am "github.com/autometrics-dev/autometrics-go/pkg/autometrics" "github.com/dave/dst" - "github.com/dave/dst/decorator" ) const ( - vanillaContext = "context" - gin = "github.com/gin-gonic/gin" - buffalo = "github.com/gobuffalo/buffalo" - echoV4 = "github.com/labstack/echo/v4" - netHttp = "net/http" + deferDecoration = "//autometrics:defer" ) // injectDeferStatement add all the necessary information into context to produce the correct defer instrumentation statement. +// +// injectDeferStatement is _always_ meant to be called after injectContextStatement, so the injection will always try to happen after the +// statemtent marked with the shadowing marker func injectDeferStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) error { - err := detectContext(ctx, funcDeclaration) - if err != nil { - return fmt.Errorf("failed to get context for tracing: %w", err) + contextAssignmentIndex, found := findContextStatement(ctx, funcDeclaration) + if !found { + return fmt.Errorf("getting context: the %v statement is missing", contextDecoration) } - firstStatement := funcDeclaration.Body.List[0] + variable, err := errorReturnValueName(funcDeclaration) if err != nil { - return fmt.Errorf("failed to get error return value name: %w", err) + return fmt.Errorf("getting error return value name: %w", err) } if len(variable) == 0 { @@ -43,34 +37,41 @@ func injectDeferStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.F autometricsDeferStatement, err := buildAutometricsDeferStatement(ctx, variable) if err != nil { - return fmt.Errorf("failed to build the defer statement for instrumentation: %w", err) + return fmt.Errorf("building the defer statement for instrumentation: %w", err) } - if deferStatement, ok := firstStatement.(*dst.DeferStmt); ok { - decorations := deferStatement.Decorations().End + funcDeclaration.Body.List = insertStatements(funcDeclaration.Body.List, contextAssignmentIndex+1, []dst.Stmt{&autometricsDeferStatement}) + return nil +} - if slices.Contains(decorations.All(), "//autometrics:defer") { - funcDeclaration.Body.List[0] = &autometricsDeferStatement - } else { - funcDeclaration.Body.List = append([]dst.Stmt{&autometricsDeferStatement}, funcDeclaration.Body.List...) - } - } else { - funcDeclaration.Body.List = append([]dst.Stmt{&autometricsDeferStatement}, funcDeclaration.Body.List...) +func insertStatements(inputArray []dst.Stmt, index int, values []dst.Stmt) []dst.Stmt { + if len(inputArray) == index { // nil or empty slice or after last element + return append(inputArray, values...) } - return nil + + beginning := inputArray[:index] + // Maybe the deep copy is not necessary, wasn't able to + // specify the semantics properly here. + end := make([]dst.Stmt, len(inputArray[index:])) + copy(end, inputArray[index:]) + + inputArray = append(beginning, values...) + inputArray = append(inputArray, end...) + + return inputArray } // removeDeferStatement removes, if detected, a previously injected defer statement. func removeDeferStatement(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) error { - firstStatement := funcDeclaration.Body.List[0] - - if deferStatement, ok := firstStatement.(*dst.DeferStmt); ok { - decorations := deferStatement.Decorations().End - if slices.Contains(decorations.All(), "//autometrics:defer") { - funcDeclaration.Body.List = funcDeclaration.Body.List[1:] + for index, statement := range funcDeclaration.Body.List { + if deferStatement, ok := statement.(*dst.DeferStmt); ok { + decorations := deferStatement.Decorations().End + if slices.Contains(decorations.All(), deferDecoration) { + funcDeclaration.Body.List = append(funcDeclaration.Body.List[:index], funcDeclaration.Body.List[index+1:]...) + return nil + } } } - return nil } @@ -99,104 +100,9 @@ func errorReturnValueName(funcNode *dst.FuncDecl) (string, error) { return "", nil } -// buildAutometricsContextNode creates an AST node representing the runtime context to inject in the instrumented code. -// -// This AST node is later used to create the defer statement responsible for instrumenting the code. -func buildAutometricsContextNode(agc *internal.GeneratorContext) (*dst.CallExpr, error) { - // Using https://github.com/dave/dst/issues/73 workaround - - var options []string - - if agc.RuntimeCtx.TraceIDGetter != "" { - options = append(options, fmt.Sprintf("%vWithTraceID(%v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.TraceIDGetter)) - } - if agc.RuntimeCtx.SpanIDGetter != "" { - options = append(options, fmt.Sprintf("%vWithSpanID(%v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.SpanIDGetter)) - } - - options = append(options, - fmt.Sprintf("%vWithConcurrentCalls(%#v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.TrackConcurrentCalls), - fmt.Sprintf("%vWithCallerName(%#v)", autometricsNamespacePrefix(agc), agc.RuntimeCtx.TrackCallerName), - ) - - if agc.RuntimeCtx.AlertConf != nil { - options = append(options, fmt.Sprintf("%vWithSloName(%#v)", - autometricsNamespacePrefix(agc), - agc.RuntimeCtx.AlertConf.ServiceName, - )) - if agc.RuntimeCtx.AlertConf.Latency != nil { - options = append(options, fmt.Sprintf("%vWithAlertLatency(%#v * time.Nanosecond, %#v)", - autometricsNamespacePrefix(agc), - agc.RuntimeCtx.AlertConf.Latency.Target, - agc.RuntimeCtx.AlertConf.Latency.Objective, - )) - } - if agc.RuntimeCtx.AlertConf.Success != nil { - options = append(options, fmt.Sprintf("%vWithAlertSuccess(%#v)", - autometricsNamespacePrefix(agc), - agc.RuntimeCtx.AlertConf.Success.Objective)) - } - } - - var buf strings.Builder - _, err := fmt.Fprintf( - &buf, - ` -package main - -var dummy = %vNewContext( - %s, -`, - autometricsNamespacePrefix(agc), - agc.RuntimeCtx.ContextVariableName, - ) - if err != nil { - return nil, fmt.Errorf("could not write string builder to build dummy source code: %w", err) - } - - for _, o := range options { - _, err = fmt.Fprintf(&buf, "\t%s,\n", o) - if err != nil { - return nil, fmt.Errorf("could not write string builder to build dummy source code: %w", err) - } - } - - _, err = fmt.Fprint(&buf, ")\n") - if err != nil { - return nil, fmt.Errorf("could not write string builder to build dummy source code: %w", err) - } - - sourceCode := buf.String() - sourceAst, err := decorator.Parse(sourceCode) - if err != nil { - return nil, fmt.Errorf( - "could not parse dummy code\n%s\n: %w", - sourceCode, - err, - ) - } - - genDeclNode, ok := sourceAst.Decls[0].(*dst.GenDecl) - if !ok { - return nil, fmt.Errorf("unexpected node in the dummy code (expected dst.GenDecl): %w", err) - } - - specNode, ok := genDeclNode.Specs[0].(*dst.ValueSpec) - if !ok { - return nil, fmt.Errorf("unexpected node in the dummy code (expected dst.ValueSpec): %w", err) - } - - callExpr, ok := specNode.Values[0].(*dst.CallExpr) - if !ok { - return nil, fmt.Errorf("unexpected node in the dummy code (expected dst.CallExpr): %w", err) - } - - return callExpr, nil -} - // buildAutometricsDeferStatement builds the AST node for the defer instrumentation statement to be inserted. -func buildAutometricsDeferStatement(ctx *internal.GeneratorContext, secondVar string) (dst.DeferStmt, error) { - preInstrumentArg, err := buildAutometricsContextNode(ctx) +func buildAutometricsDeferStatement(ctx *internal.GeneratorContext, errorPointerVariable string) (dst.DeferStmt, error) { + _, contextName, err := buildAutometricsContextNode(ctx) if err != nil { return dst.DeferStmt{}, fmt.Errorf("could not generate the runtime context value: %w", err) } @@ -204,19 +110,14 @@ func buildAutometricsDeferStatement(ctx *internal.GeneratorContext, secondVar st Call: &dst.CallExpr{ Fun: dst.NewIdent(fmt.Sprintf("%vInstrument", autometricsNamespacePrefix(ctx))), Args: []dst.Expr{ - &dst.CallExpr{ - Fun: dst.NewIdent(fmt.Sprintf("%vPreInstrument", autometricsNamespacePrefix(ctx))), - Args: []dst.Expr{ - preInstrumentArg, - }, - }, - dst.NewIdent(secondVar), + dst.NewIdent(contextName), + dst.NewIdent(errorPointerVariable), }, }, } statement.Decs.Before = dst.NewLine - statement.Decs.End = []string{"//autometrics:defer"} + statement.Decs.End = []string{deferDecoration} statement.Decs.After = dst.EmptyLine return statement, nil @@ -229,156 +130,3 @@ func autometricsNamespacePrefix(ctx *internal.GeneratorContext) string { return fmt.Sprintf("%v.", ctx.FuncCtx.ImplImportName) } } - -// detectContextIdentImpl is a Context detection logic helper for arguments whose type is an identifier -// -// The function returns true when it found enough information to ask for iteration to stop. -func detectContextIdentImpl(ctx *internal.GeneratorContext, argName string, ident *dst.Ident) (bool, error) { - typeName := ident.Name - // If argType is just a dst.Ident when parsing, that means - // it is a single identifier ('Context', _not_ 'context.Context'). - // Therefore we can solely check imports that got imported as '.' - for alias, canonical := range ctx.ImportsMap { - if alias != "." { - continue - } - - if canonical == vanillaContext && typeName == "Context" { - ctx.RuntimeCtx.ContextVariableName = argName - ctx.RuntimeCtx.SpanIDGetter = "" - ctx.RuntimeCtx.TraceIDGetter = "" - return true, nil - } - - if canonical == netHttp && typeName == "Request" { - if argName == "_" { - log.Println("Warning: an unnamed net/http.Request has been detected. To make Autometrics reuse its context for tracing purposes, please name it, and run 'go generate' again") - ctx.RuntimeCtx.ContextVariableName = "nil" - } else { - ctx.RuntimeCtx.ContextVariableName = fmt.Sprintf("%s.Context()", argName) - } - ctx.RuntimeCtx.SpanIDGetter = "" - ctx.RuntimeCtx.TraceIDGetter = "" - return true, nil - } - - if canonical == gin && typeName == "Context" { - ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) - ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) - return true, nil - } - - // Buffalo context embeds a context.Context so it can work like vanilla - if canonical == buffalo && typeName == "Context" { - ctx.RuntimeCtx.ContextVariableName = argName - ctx.RuntimeCtx.SpanIDGetter = "" - ctx.RuntimeCtx.TraceIDGetter = "" - return true, nil - } - - if canonical == echoV4 && typeName == "Context" { - ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) - ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) - return true, nil - } - } - - return false, nil -} - -// detectContextIdentImpl is a Context detection logic helper for arguments whose type is a selector expression. -// -// The function returns true when it found enough information to ask for iteration to stop. -func detectContextSelectorImpl(ctx *internal.GeneratorContext, argName string, selector *dst.SelectorExpr) (bool, error) { - typeName := selector.Sel.Name - if parent, p_ok := selector.X.(*dst.Ident); p_ok { - parentName := parent.Name - for alias, canonical := range ctx.ImportsMap { - if canonical == vanillaContext && parentName == alias && typeName == "Context" { - ctx.RuntimeCtx.ContextVariableName = argName - ctx.RuntimeCtx.SpanIDGetter = "" - ctx.RuntimeCtx.TraceIDGetter = "" - return true, nil - } - - if canonical == netHttp && parentName == alias && typeName == "Request" { - ctx.RuntimeCtx.ContextVariableName = fmt.Sprintf("%s.Context()", argName) - if argName == "_" { - log.Println("Warning: an unnamed net/http.Request has been detected. To make Autometrics reuse its context for tracing purposes, please name it, and run 'go generate' again") - ctx.RuntimeCtx.ContextVariableName = "nil" - } else { - ctx.RuntimeCtx.ContextVariableName = fmt.Sprintf("%s.Context()", argName) - } - ctx.RuntimeCtx.SpanIDGetter = "" - ctx.RuntimeCtx.TraceIDGetter = "" - return true, nil - } - - if canonical == gin && parentName == alias && typeName == "Context" { - ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) - ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.GetString(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) - return true, nil - } - - // Buffalo context embeds a context.Context so it can work like vanilla - if canonical == buffalo && parentName == alias && typeName == "Context" { - ctx.RuntimeCtx.ContextVariableName = argName - ctx.RuntimeCtx.SpanIDGetter = "" - ctx.RuntimeCtx.TraceIDGetter = "" - return true, nil - } - - if canonical == echoV4 && typeName == "Context" && (parentName == alias || parentName == "echo") { - ctx.RuntimeCtx.SpanIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareSpanIDKey) - ctx.RuntimeCtx.TraceIDGetter = fmt.Sprintf("%s.DecodeString(%s.Get(%#v))", ctx.FuncCtx.ImplImportName, argName, am.MiddlewareTraceIDKey) - return true, nil - } - } - } else { - // TODO: log that autometrics cannot detect multi-nested contexts instead of errorring - // continue - return true, fmt.Errorf("expecting parent to be an identifier, got %s instead", reflect.TypeOf(selector.X).String()) - } - return false, nil -} - -// detectContext modifies a RuntimeCtxInfo to inject context when detected in the function signature. -func detectContext(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl) error { - arguments := funcDeclaration.Type.Params.List - for _, argGroup := range arguments { - if len(argGroup.Names) > 1 { - continue - } - argName := argGroup.Names[0].Name - if argGroup.Type == nil { - continue - } - - if argType, ok := argGroup.Type.(*dst.Ident); ok { - if found, err := detectContextIdentImpl(ctx, argName, argType); found { - return err - } - } else if argType, ok := argGroup.Type.(*dst.SelectorExpr); ok { - if found, err := detectContextSelectorImpl(ctx, argName, argType); found { - return err - } - } else if argType, ok := argGroup.Type.(*dst.StarExpr); ok { - if ident, ok := argType.X.(*dst.Ident); ok { - if found, err := detectContextIdentImpl(ctx, argName, ident); found { - return err - } - } else if selector, ok := argType.X.(*dst.SelectorExpr); ok { - if found, err := detectContextSelectorImpl(ctx, argName, selector); found { - return err - } - } else { - return fmt.Errorf("expecting the type being pointed to to be an identifier, got %s instead", reflect.TypeOf(argType.X).String()) - } - } else { - return fmt.Errorf("expecting the type of argGroup to be an identifier, got %s instead", reflect.TypeOf(argGroup.Type).String()) - } - } - - ctx.RuntimeCtx.ContextVariableName = "nil" - return nil -} diff --git a/internal/generate/defer_test.go b/internal/generate/defer_test.go index 4f8ee6c..ff787ec 100644 --- a/internal/generate/defer_test.go +++ b/internal/generate/defer_test.go @@ -42,13 +42,14 @@ func main(thisIsAContext context.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext context.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tthisIsAContext = prom.PreInstrument(prom.NewContext(\n" + "\t\tthisIsAContext,\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(thisIsAContext, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -99,13 +100,14 @@ func main(thisIsAContext vanilla.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext vanilla.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tthisIsAContext = prom.PreInstrument(prom.NewContext(\n" + "\t\tthisIsAContext,\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(thisIsAContext, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -156,13 +158,14 @@ func main(thisIsAContext Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tthisIsAContext = prom.PreInstrument(prom.NewContext(\n" + "\t\tthisIsAContext,\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(thisIsAContext, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -213,13 +216,14 @@ func main(w http.ResponseWriter, req *http.Request) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(w http.ResponseWriter, req *http.Request) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\treq.Context(),\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -270,13 +274,14 @@ func main(w vanilla.ResponseWriter, req *vanilla.Request) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(w vanilla.ResponseWriter, req *vanilla.Request) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\treq.Context(),\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -327,13 +332,14 @@ func main(w ResponseWriter, req *Request) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(w ResponseWriter, req *Request) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\treq.Context(),\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -384,13 +390,14 @@ func main(thisIsAContext buffalo.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext buffalo.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tthisIsAContext = prom.PreInstrument(prom.NewContext(\n" + "\t\tthisIsAContext,\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(thisIsAContext, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -441,13 +448,14 @@ func main(thisIsAContext vanilla.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext vanilla.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tthisIsAContext = prom.PreInstrument(prom.NewContext(\n" + "\t\tthisIsAContext,\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(thisIsAContext, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -498,13 +506,14 @@ func main(thisIsAContext Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tthisIsAContext = prom.PreInstrument(prom.NewContext(\n" + "\t\tthisIsAContext,\n" + "\t\tprom.WithConcurrentCalls(true),\n" + "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(thisIsAContext, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -555,7 +564,7 @@ func main(thisIsAContext echo.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext echo.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\tnil,\n" + "\t\tprom.WithTraceID(prom.DecodeString(thisIsAContext.Get(\"autometricsTraceID\"))),\n" + "\t\tprom.WithSpanID(prom.DecodeString(thisIsAContext.Get(\"autometricsSpanID\"))),\n" + @@ -563,7 +572,8 @@ func main(thisIsAContext echo.Context) { "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -614,7 +624,7 @@ func main(thisIsAContext vanilla.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext vanilla.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\tnil,\n" + "\t\tprom.WithTraceID(prom.DecodeString(thisIsAContext.Get(\"autometricsTraceID\"))),\n" + "\t\tprom.WithSpanID(prom.DecodeString(thisIsAContext.Get(\"autometricsSpanID\"))),\n" + @@ -622,7 +632,8 @@ func main(thisIsAContext vanilla.Context) { "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -673,7 +684,7 @@ func main(thisIsAContext Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\tnil,\n" + "\t\tprom.WithTraceID(prom.DecodeString(thisIsAContext.Get(\"autometricsTraceID\"))),\n" + "\t\tprom.WithSpanID(prom.DecodeString(thisIsAContext.Get(\"autometricsSpanID\"))),\n" + @@ -681,7 +692,8 @@ func main(thisIsAContext Context) { "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -732,7 +744,7 @@ func main(thisIsAContext *gin.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext *gin.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\tnil,\n" + "\t\tprom.WithTraceID(prom.DecodeString(thisIsAContext.GetString(\"autometricsTraceID\"))),\n" + "\t\tprom.WithSpanID(prom.DecodeString(thisIsAContext.GetString(\"autometricsSpanID\"))),\n" + @@ -740,7 +752,8 @@ func main(thisIsAContext *gin.Context) { "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -791,7 +804,7 @@ func main(thisIsAContext *vanilla.Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext *vanilla.Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\tnil,\n" + "\t\tprom.WithTraceID(prom.DecodeString(thisIsAContext.GetString(\"autometricsTraceID\"))),\n" + "\t\tprom.WithSpanID(prom.DecodeString(thisIsAContext.GetString(\"autometricsSpanID\"))),\n" + @@ -799,7 +812,8 @@ func main(thisIsAContext *vanilla.Context) { "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" @@ -850,7 +864,7 @@ func main(thisIsAContext *Context) { "//\n" + "//autometrics:inst --no-doc --slo \"Service Test\" --success-target 99\n" + "func main(thisIsAContext *Context) {\n" + - "\tdefer prom.Instrument(prom.PreInstrument(prom.NewContext(\n" + + "\tamCtx := prom.PreInstrument(prom.NewContext(\n" + "\t\tnil,\n" + "\t\tprom.WithTraceID(prom.DecodeString(thisIsAContext.GetString(\"autometricsTraceID\"))),\n" + "\t\tprom.WithSpanID(prom.DecodeString(thisIsAContext.GetString(\"autometricsSpanID\"))),\n" + @@ -858,7 +872,8 @@ func main(thisIsAContext *Context) { "\t\tprom.WithCallerName(true),\n" + "\t\tprom.WithSloName(\"Service Test\"),\n" + "\t\tprom.WithAlertSuccess(99),\n" + - "\t)), nil) //autometrics:defer\n" + + "\t)) //autometrics:shadow-ctx\n" + + "\tdefer prom.Instrument(amCtx, nil) //autometrics:defer\n" + "\n" + " fmt.Println(hello) // line comment 3\n" + "}\n" diff --git a/internal/generate/generate.go b/internal/generate/generate.go index 5f61d06..4bb8d72 100644 --- a/internal/generate/generate.go +++ b/internal/generate/generate.go @@ -28,6 +28,23 @@ const ( AmOtelPackage = "\"github.com/autometrics-dev/autometrics-go/otel/autometrics\"" ) +type GenerateError struct { + FunctionName string + Detail error +} + +type GenerateErrors []GenerateError + +func (errs GenerateErrors) Error() string { + var sb strings.Builder + + for _, err := range errs { + sb.WriteString(fmt.Sprintf("in %v: %v\n", err.FunctionName, err.Detail.Error())) + } + + return sb.String() +} + // TransformFile takes a file path and generates the documentation // for the `//autometrics:inst` functions. // @@ -53,7 +70,7 @@ func TransformFile(ctx internal.GeneratorContext, path, moduleName string) error sourceCode := string(sourceBytes) transformedSource, err := GenerateDocumentationAndInstrumentation(ctx, sourceCode, moduleName) if err != nil { - return fmt.Errorf("error generating documentation: %w", err) + return fmt.Errorf("errors generating instrumentation and documentation: %w", err) } err = os.WriteFile(path, []byte(transformedSource), permissions) @@ -71,10 +88,10 @@ func TransformFile(ctx internal.GeneratorContext, path, moduleName string) error func GenerateDocumentationAndInstrumentation(ctx internal.GeneratorContext, sourceCode, moduleName string) (string, error) { fileTree, err := decorator.Parse(sourceCode) if err != nil { - return "", fmt.Errorf("error parsing source code: %w", err) + return "", fmt.Errorf("parsing source code: %w", err) } - var inspectErr error + var inspectErr GenerateErrors var foundAmImport bool for _, importSpec := range fileTree.Imports { @@ -87,7 +104,7 @@ func GenerateDocumentationAndInstrumentation(ctx internal.GeneratorContext, sour if !ctx.RemoveEverything && !foundAmImport { err = addAutometricsImport(&ctx, fileTree) if err != nil { - return "", fmt.Errorf("error adding the autometrics import: %w", err) + return "", fmt.Errorf("adding the autometrics import: %w", err) } } @@ -97,11 +114,10 @@ func GenerateDocumentationAndInstrumentation(ctx internal.GeneratorContext, sour fileWalk := func(node dst.Node) bool { if funcDeclaration, ok := node.(*dst.FuncDecl); ok { - inspectErr = walkFuncDeclaration(&ctx, funcDeclaration, moduleName) - } - - if inspectErr != nil { - return false + individualError := walkFuncDeclaration(&ctx, funcDeclaration, moduleName) + if individualError != nil { + inspectErr = append(inspectErr, *individualError) + } } return true @@ -110,28 +126,37 @@ func GenerateDocumentationAndInstrumentation(ctx internal.GeneratorContext, sour dst.Inspect(fileTree, fileWalk) if inspectErr != nil { - return "", fmt.Errorf("error while transforming file in %v: %w", moduleName, inspectErr) + return "", fmt.Errorf("transforming file in %v: %w", moduleName, inspectErr) } var buf strings.Builder err = decorator.Fprint(&buf, fileTree) if err != nil { - return "", fmt.Errorf("error writing the AST to buffer: %w", err) + return "", fmt.Errorf("writing the AST to buffer: %w", err) } return buf.String(), nil } // walkFuncDeclaration uses the context to generate documentation and code if necessary for a function declaration in a file. -func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl, moduleName string) error { +func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.FuncDecl, moduleName string) *GenerateError { if !ctx.RemoveEverything && ctx.FuncCtx.ImplImportName == "" { if ctx.Implementation == autometrics.PROMETHEUS { - return fmt.Errorf("the source file is missing a %v import", AmPromPackage) + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf("the source file is missing a %v import", AmPromPackage), + } } else if ctx.Implementation == autometrics.OTEL { - return fmt.Errorf("the source file is missing a %v import", AmOtelPackage) + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf("the source file is missing a %v import", AmOtelPackage), + } } else { - return fmt.Errorf("unknown implementation of metrics has been queried") + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf("unknown implementation of metrics has been queried"), + } } } @@ -144,15 +169,31 @@ func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.Fu // Clean up old autometrics comments docComments, err := cleanUpAutometricsComments(*ctx, funcDeclaration) if err != nil { - return fmt.Errorf("error trying to remove autometrics comment from former pass: %w", err) + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf("removing autometrics comment from former pass: %w", err), + } } err = removeDeferStatement(ctx, funcDeclaration) if err != nil { - return fmt.Errorf( - "error removing an older autometrics defer statement in %v: %w", - funcDeclaration.Name.Name, - err) + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf( + "removing an older autometrics defer statement in %v: %w", + funcDeclaration.Name.Name, + err), + } + } + err = removeContextStatement(ctx, funcDeclaration) + if err != nil { + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf( + "removing an older autometrics context statement in %v: %w", + funcDeclaration.Name.Name, + err), + } } // Early exit if we wanted to remove everything @@ -164,10 +205,13 @@ func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.Fu // Detect autometrics directive err = parseAutometricsFnContext(ctx, docComments) if err != nil { - return fmt.Errorf( - "failed to parse //autometrics directive for %v: %w", - funcDeclaration.Name.Name, - err) + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf( + "parsing //autometrics directive for %v: %w", + funcDeclaration.Name.Name, + err), + } } // This block only runs on functions that still have the autometrics directive @@ -192,10 +236,22 @@ func walkFuncDeclaration(ctx *internal.GeneratorContext, funcDeclaration *dst.Fu funcDeclaration.Decorations().Start.Replace(docComments...) } + // context statement + _, err := injectContextStatement(ctx, funcDeclaration) + if err != nil { + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf("injecting context statement: %w", err), + } + } + // defer statement - err := injectDeferStatement(ctx, funcDeclaration) + err = injectDeferStatement(ctx, funcDeclaration) if err != nil { - return fmt.Errorf("failed to inject defer statement: %w", err) + return &GenerateError{ + FunctionName: funcDeclaration.Name.Name, + Detail: fmt.Errorf("injecting defer statement: %w", err), + } } } return nil @@ -213,7 +269,7 @@ func parseAutometricsFnContext(ctx *internal.GeneratorContext, commentGroup []st tokens, err := shlex.Split(args) if err != nil { - return fmt.Errorf("could not parse the directive arguments: %w", err) + return fmt.Errorf("parsing the directive arguments: %w", err) } tokenIndex := 0 for tokenIndex < len(tokens) { @@ -222,22 +278,22 @@ func parseAutometricsFnContext(ctx *internal.GeneratorContext, commentGroup []st case token == SloNameArgument: tokenIndex, err = parseSloName(tokenIndex, tokens, ctx) if err != nil { - return fmt.Errorf("error parsing %v argument: %w", SloNameArgument, err) + return fmt.Errorf("parsing %v argument: %w", SloNameArgument, err) } case token == SuccessObjArgument: tokenIndex, err = parseSuccessObjective(tokenIndex, tokens, ctx) if err != nil { - return fmt.Errorf("error parsing %v argument: %w", SuccessObjArgument, err) + return fmt.Errorf("parsing %v argument: %w", SuccessObjArgument, err) } case token == LatencyMsArgument: tokenIndex, err = parseLatencyMs(tokenIndex, tokens, ctx) if err != nil { - return fmt.Errorf("error parsing %v argument: %w", LatencyMsArgument, err) + return fmt.Errorf("parsing %v argument: %w", LatencyMsArgument, err) } case token == LatencyObjArgument: tokenIndex, err = parseLatencyObjective(tokenIndex, tokens, ctx) if err != nil { - return fmt.Errorf("error parsing %v argument: %w", LatencyObjArgument, err) + return fmt.Errorf("parsing %v argument: %w", LatencyObjArgument, err) } case token == NoDocArgument: ctx.FuncCtx.DisableDocGeneration = true diff --git a/internal/generate/generate_test.go b/internal/generate/generate_test.go index 431c88c..d95a602 100644 --- a/internal/generate/generate_test.go +++ b/internal/generate/generate_test.go @@ -69,13 +69,14 @@ import ( // //autometrics:inst --slo "Service Test" --success-target 99 func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), prom.WithSloName("Service Test"), prom.WithAlertSuccess(99), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -148,13 +149,14 @@ import ( // //autometrics:inst --slo "Service Test" --success-target 99 func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), prom.WithSloName("Service Test"), prom.WithAlertSuccess(99), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -199,13 +201,14 @@ import ( // //autometrics:inst --no-doc --slo "Service Test" --success-target 99 func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), prom.WithSloName("Service Test"), prom.WithAlertSuccess(99), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -271,11 +274,12 @@ import ( // [Request Rate Callee]: http://localhost:9090/graph?g0.expr=%23+Rate+of+function+calls+emanating+from+%60main%60+function+per+second%2C+averaged+over+5+minute+windows%0A%0Asum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bcaller_function%3D%22main%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29&g0.tab=0 // [Error Ratio Callee]: http://localhost:9090/graph?g0.expr=%23+Percentage+of+function+emanating+from+%60main%60+function+that+return+errors%2C+averaged+over+5+minute+windows%0A%0A%28sum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bcaller_function%3D%22main%22%2Cresult%3D%22error%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29+%2F+%28sum+by+%28function%2C+module%2C+service_name%2C+version%2C+commit%29+%28rate%28function_calls_total%7Bcaller_function%3D%22main%22%7D%5B5m%5D%29+%2A+on+%28instance%2C+job%29+group_left%28version%2C+commit%29+last_over_time%28build_info%5B1s%5D%29%29%29&g0.tab=0 func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -315,11 +319,12 @@ import ( ) func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -361,13 +366,14 @@ import ( //autometrics:inst --no-doc --slo "Service Test" --success-target 99 func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), prom.WithSloName("Service Test"), prom.WithAlertSuccess(99), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -525,13 +531,14 @@ import ( // //autometrics:inst --slo "API" --latency-target 99.9 --latency-ms 500 func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), prom.WithSloName("API"), prom.WithAlertLatency(500000000*time.Nanosecond, 99.9), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -573,13 +580,14 @@ import "github.com/autometrics-dev/autometrics-go/prometheus/autometrics" // //autometrics:inst --no-doc --slo "API" --latency-target 99.9 --latency-ms 500 func main() { - defer autometrics.Instrument(autometrics.PreInstrument(autometrics.NewContext( + amCtx := autometrics.PreInstrument(autometrics.NewContext( nil, autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertLatency(500000000*time.Nanosecond, 99.9), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer autometrics.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -630,13 +638,14 @@ import ( // //autometrics:inst --no-doc --slo "API" --latency-target 99.9 --latency-ms 500 func main() { - defer autometrics.Instrument(autometrics.PreInstrument(autometrics.NewContext( + amCtx := autometrics.PreInstrument(autometrics.NewContext( nil, autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertLatency(500000000*time.Nanosecond, 99.9), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer autometrics.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -687,13 +696,14 @@ import "github.com/autometrics-dev/autometrics-go/prometheus/autometrics" // This comment is associated with the main function. //autometrics:inst --no-doc --slo "API" --latency-target 99.9 --latency-ms 500 func main() { - defer autometrics.Instrument(autometrics.PreInstrument(autometrics.NewContext( + amCtx := autometrics.PreInstrument(autometrics.NewContext( nil, autometrics.WithConcurrentCalls(true), autometrics.WithCallerName(true), autometrics.WithSloName("API"), autometrics.WithAlertLatency(500000000*time.Nanosecond, 99.9), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer autometrics.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -751,13 +761,14 @@ import ( // //autometrics:inst --slo "API" --latency-target 99.9 --latency-ms 500 func main() { - defer prom.Instrument(prom.PreInstrument(prom.NewContext( + amCtx := prom.PreInstrument(prom.NewContext( nil, prom.WithConcurrentCalls(true), prom.WithCallerName(true), prom.WithSloName("API"), prom.WithAlertLatency(500000000*time.Nanosecond, 99.9), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer prom.Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } @@ -1388,7 +1399,7 @@ func implementContextCodeGenTest(t *testing.T, contextToSerialize internal.Runti }, } - node, err := buildAutometricsContextNode(&sourceContext) + node, _, err := buildAutometricsContextNode(&sourceContext) if err != nil { t.Fatalf("error building the context node: %s", err) } @@ -1526,13 +1537,14 @@ import _ "github.com/autometrics-dev/autometrics-go/prometheus/autometrics" // //autometrics:inst --no-doc --slo "API" --latency-target 99.9 --latency-ms 500 func main() { - defer Instrument(PreInstrument(NewContext( + amCtx := PreInstrument(NewContext( nil, WithConcurrentCalls(true), WithCallerName(true), WithSloName("API"), WithAlertLatency(500000000*time.Nanosecond, 99.9), - )), nil) //autometrics:defer + )) //autometrics:shadow-ctx + defer Instrument(amCtx, nil) //autometrics:defer fmt.Println(hello) // line comment 3 } diff --git a/otel/autometrics/instrument.go b/otel/autometrics/instrument.go index 38edd56..955d11d 100644 --- a/otel/autometrics/instrument.go +++ b/otel/autometrics/instrument.go @@ -47,10 +47,10 @@ func Instrument(ctx context.Context, err *error) { functionCallsCount.Add(ctx, 1, metric.WithAttributes([]attribute.KeyValue{ - attribute.Key(FunctionLabel).String(callInfo.FuncName), - attribute.Key(ModuleLabel).String(callInfo.ModuleName), - attribute.Key(CallerFunctionLabel).String(callInfo.ParentFuncName), - attribute.Key(CallerModuleLabel).String(callInfo.ParentModuleName), + attribute.Key(FunctionLabel).String(callInfo.Current.Function), + attribute.Key(ModuleLabel).String(callInfo.Current.Module), + attribute.Key(CallerFunctionLabel).String(callInfo.Parent.Function), + attribute.Key(CallerModuleLabel).String(callInfo.Parent.Module), attribute.Key(ResultLabel).String(result), attribute.Key(TargetSuccessRateLabel).String(successObjective), attribute.Key(SloNameLabel).String(sloName), @@ -62,10 +62,10 @@ func Instrument(ctx context.Context, err *error) { }...)) functionCallsDuration.Record(ctx, time.Since(am.GetStartTime(ctx)).Seconds(), metric.WithAttributes([]attribute.KeyValue{ - attribute.Key(FunctionLabel).String(callInfo.FuncName), - attribute.Key(ModuleLabel).String(callInfo.ModuleName), - attribute.Key(CallerFunctionLabel).String(callInfo.ParentFuncName), - attribute.Key(CallerModuleLabel).String(callInfo.ParentModuleName), + attribute.Key(FunctionLabel).String(callInfo.Current.Function), + attribute.Key(ModuleLabel).String(callInfo.Current.Module), + attribute.Key(CallerFunctionLabel).String(callInfo.Parent.Function), + attribute.Key(CallerModuleLabel).String(callInfo.Parent.Module), attribute.Key(TargetLatencyLabel).String(latencyTarget), attribute.Key(TargetSuccessRateLabel).String(latencyObjective), attribute.Key(SloNameLabel).String(sloName), @@ -79,10 +79,10 @@ func Instrument(ctx context.Context, err *error) { if am.GetTrackConcurrentCalls(ctx) { functionCallsConcurrent.Add(ctx, -1, metric.WithAttributes([]attribute.KeyValue{ - attribute.Key(FunctionLabel).String(callInfo.FuncName), - attribute.Key(ModuleLabel).String(callInfo.ModuleName), - attribute.Key(CallerFunctionLabel).String(callInfo.ParentFuncName), - attribute.Key(CallerModuleLabel).String(callInfo.ParentModuleName), + attribute.Key(FunctionLabel).String(callInfo.Current.Function), + attribute.Key(ModuleLabel).String(callInfo.Current.Module), + attribute.Key(CallerFunctionLabel).String(callInfo.Parent.Function), + attribute.Key(CallerModuleLabel).String(callInfo.Parent.Module), attribute.Key(CommitLabel).String(buildInfo.Commit), attribute.Key(VersionLabel).String(buildInfo.Version), attribute.Key(BranchLabel).String(buildInfo.Branch), @@ -90,6 +90,11 @@ func Instrument(ctx context.Context, err *error) { attribute.Key(JobNameLabel).String(am.GetPushJobName()), }...)) } + + // NOTE: This call means that goroutines that outlive this function as the caller will not have access to parent + // caller information, but hopefully by that point we got all the necessary accesses done. + // If not, it is a convenience we accept to give up to prevent memory usage from exploding + _ = am.PopFunctionName(ctx) } // PreInstrument runs the "before wrappee" part of instrumentation. @@ -101,19 +106,19 @@ func PreInstrument(ctx context.Context) context.Context { return nil } - callInfo := am.CallerInfo() - ctx = am.SetCallInfo(ctx, callInfo) + ctx = am.FillTracingAndCallerInfo(ctx) ctx = am.FillBuildInfo(ctx) - ctx = am.FillTracingInfo(ctx) + + callInfo := am.GetCallInfo(ctx) if am.GetTrackConcurrentCalls(ctx) { buildInfo := am.GetBuildInfo(ctx) functionCallsConcurrent.Add(ctx, 1, metric.WithAttributes([]attribute.KeyValue{ - attribute.Key(FunctionLabel).String(callInfo.FuncName), - attribute.Key(ModuleLabel).String(callInfo.ModuleName), - attribute.Key(CallerFunctionLabel).String(callInfo.ParentFuncName), - attribute.Key(CallerModuleLabel).String(callInfo.ParentModuleName), + attribute.Key(FunctionLabel).String(callInfo.Current.Function), + attribute.Key(ModuleLabel).String(callInfo.Current.Module), + attribute.Key(CallerFunctionLabel).String(callInfo.Parent.Function), + attribute.Key(CallerModuleLabel).String(callInfo.Parent.Module), attribute.Key(CommitLabel).String(buildInfo.Commit), attribute.Key(VersionLabel).String(buildInfo.Version), attribute.Key(BranchLabel).String(buildInfo.Branch), diff --git a/otel/autometrics/otel.go b/otel/autometrics/otel.go index 4fcd437..dea2f4d 100644 --- a/otel/autometrics/otel.go +++ b/otel/autometrics/otel.go @@ -35,6 +35,10 @@ var ( ) const ( + // AutometricsSpecVersion is the version of the specification the library follows + // The specifications can be found in https://github.com/autometrics-dev/autometrics-shared/tree/main/specs + AutometricsSpecVersion = "1.0.0" + // FunctionCallsCountName is the name of the openTelemetry metric for the counter of calls to specific functions. FunctionCallsCountName = "function.calls" // FunctionCallsDurationName is the name of the openTelemetry metric for the duration histogram of calls to specific functions. @@ -84,6 +88,17 @@ const ( // BranchLabel is the openTelemetry attribute that describes the branch of the build of the monitored codebase. BranchLabel = "branch" + // RepositoryURLLabel is the openTelemetry attribute that describes the URL at which the repository containing + // the monitored service can be found + RepositoryURLLabel = "repository.url" + // RepositoryProviderLabel is the openTelemetry attribute that describes the service provider for the monitored + // service repository url + RepositoryProviderLabel = "repository.provider" + + // AutometricsVersionLabel is the openTelemetry attribute that describes the version of the Autometrics specification + // the library follows + AutometricsVersionLabel = "autometrics.version" + // ServiceNameLabel is the openTelemetry attribute that describes the name of the Service being monitored. ServiceNameLabel = "service.name" @@ -190,6 +205,17 @@ func Init(meterName string, histogramBuckets []float64, buildInformation BuildIn autometrics.SetService(buildInformation.Service) } + if repoURL, ok := os.LookupEnv(autometrics.AutometricsRepoURLEnv); ok { + autometrics.SetRepositoryURL(repoURL) + } else if buildInformation.RepositoryURL != "" { + autometrics.SetRepositoryURL(buildInformation.RepositoryURL) + } + if repoProvider, ok := os.LookupEnv(autometrics.AutometricsRepoProviderEnv); ok { + autometrics.SetRepositoryURL(repoProvider) + } else if buildInformation.RepositoryProvider != "" { + autometrics.SetRepositoryURL(buildInformation.RepositoryProvider) + } + provider, err := initProvider(pushExporter, pushConfiguration, meterName, histogramBuckets) if err != nil { return nil, err @@ -223,7 +249,10 @@ func Init(meterName string, histogramBuckets []float64, buildInformation BuildIn attribute.Key(VersionLabel).String(buildInformation.Version), attribute.Key(BranchLabel).String(buildInformation.Branch), attribute.Key(ServiceNameLabel).String(autometrics.GetService()), + attribute.Key(RepositoryProviderLabel).String(autometrics.GetRepositoryProvider()), + attribute.Key(RepositoryURLLabel).String(autometrics.GetRepositoryURL()), attribute.Key(JobNameLabel).String(autometrics.GetPushJobName()), + attribute.Key(AutometricsVersionLabel).String(AutometricsSpecVersion), }...)) return cancelFunc, nil diff --git a/pkg/autometrics/ctx.go b/pkg/autometrics/ctx.go index 2988bb6..73cb129 100644 --- a/pkg/autometrics/ctx.go +++ b/pkg/autometrics/ctx.go @@ -2,6 +2,7 @@ package autometrics // import "github.com/autometrics-dev/autometrics-go/pkg/aut import ( "context" + "errors" "log" "math/rand" "time" @@ -229,12 +230,12 @@ func GetParentSpanID(c context.Context) (SpanID, bool) { return sid, ok } -// FillTracingInfo ensures the context has a traceID and a spanID. +// FillTracingAndCallerInfo ensures the context has a traceID and a spanID, and looks for relevant caller information to add in the context as well. // If they do not have this information, this method adds randomly // generated IDs in the context to be used later for exemplars // // The random generator is a PRNG, seeded with the timestamp of the first time new IDs are needed. -func FillTracingInfo(ctx context.Context) context.Context { +func FillTracingAndCallerInfo(ctx context.Context) context.Context { // We are using a PRNG because FillTracingInfo is expected to be called in PreInstrument. // Therefore it can have a noticeable impact on the performance of instrumented code. // Pseudo randomness should be enough for our use cases, true randomness might introduce too much latency. @@ -258,6 +259,19 @@ func FillTracingInfo(ctx context.Context) context.Context { ctx = SetTraceID(ctx, tid) } + callInfo := callerInfo(ctx) + ctx = SetCallInfo(ctx, callInfo) + + // Adds an entry in the global map from current (traceID, spanID) to the function ID + // NOTE: this will "leak" memory if PopFunctionName is never called for the matching (TraceId, SpanId) pair. + // Calling the cleanup function is the responsibility of the otel.Instrument() and prometheus.Instrument() + // functions as the closers. + // NOTE: This also means that goroutines that outlive their as the caller will not have access to parent + // caller information, but hopefully by that point we got all the necessary accesses done. + // If not, it is a convenience we accept to give up to prevent memory usage from exploding. + // TODO: once settled on a login library, log the error instead of ignoring it + _ = PushFunctionName(ctx, callInfo.Current) + return ctx } @@ -336,3 +350,46 @@ func GetValidHttpCodeRanges(c context.Context) []InclusiveIntRange { return ranges } + +func ParentFunctionName(ctx context.Context) (FunctionID, error) { + tid, ok := GetTraceID(ctx) + if !ok { + return FunctionID{}, errors.New("context does not have any trace ID to follow.") + } + pSpanID, ok := GetParentSpanID(ctx) + if !ok { + return FunctionID{}, errors.New("context does not have any parent span ID to follow.") + } + + return fetchFunctionName(tid, pSpanID) +} + +func PopFunctionName(ctx context.Context) error { + tid, ok := GetTraceID(ctx) + if !ok { + return errors.New("context does not have any trace ID to follow.") + } + sid, ok := GetSpanID(ctx) + if !ok { + return errors.New("context does not have any current span ID to follow.") + } + + popFunctionName(tid, sid) + + return nil +} + +func PushFunctionName(ctx context.Context, functionID FunctionID) error { + tid, ok := GetTraceID(ctx) + if !ok { + return errors.New("context does not have any trace ID to follow.") + } + sid, ok := GetSpanID(ctx) + if !ok { + return errors.New("context does not have any current span ID to follow.") + } + + pushFunctionName(tid, sid, functionID) + + return nil +} diff --git a/pkg/autometrics/global_state.go b/pkg/autometrics/global_state.go index 0c6220a..88f5c71 100644 --- a/pkg/autometrics/global_state.go +++ b/pkg/autometrics/global_state.go @@ -1,5 +1,9 @@ package autometrics // import "github.com/autometrics-dev/autometrics-go/pkg/autometrics" +import ( + "fmt" +) + // These variables are describing the state of the application being autometricized, // _not_ the build information of the binary @@ -12,17 +16,33 @@ const ( // the service to use as a label. This environment variable has precedence over variables hardcoded // in the [BuildInfo] struct in the Init call. OTelServiceNameEnv = "OTEL_SERVICE_NAME" + // AutometricsRepoURLEnv is the name of the environment variable to declare to give the URL of + // the repository for the service to use as a label. This environment variable has precedence over + // over hardcoding the variable directly in [BuildInfo] struct in the Init call. + AutometricsRepoURLEnv = "AUTOMETRICS_REPOSITORY_URL" + // AutometricsRepoProviderEnv is the name of the environment variable to declare to give the name of + // the repository provider to use as a label. This environment variable has precedence over + // over hardcoding the variable directly in [BuildInfo] struct in the Init call. + AutometricsRepoProviderEnv = "AUTOMETRICS_REPOSITORY_PROVIDER" ) var ( - version string - commit string - branch string - service string - pushJobName string - pushJobURL string + version string + commit string + branch string + service string + repoURL string + repoProvider string + pushJobName string + pushJobURL string + instrumentedSpans map[spanKey]FunctionID = make(map[spanKey]FunctionID) ) +type spanKey struct { + tid TraceID + sid SpanID +} + // GetVersion returns the version of the codebase being instrumented. func GetVersion() string { return version @@ -63,6 +83,27 @@ func SetService(newService string) { service = newService } +// GetRepositoryURL returns the URL of the repo of the codebase being instrumented. +func GetRepositoryURL() string { + return repoURL +} + +// SetRepositoryURL sets the URL of the repo of the codebase being instrumented. +func SetRepositoryURL(newRepositoryURL string) { + repoURL = newRepositoryURL + +} + +// GetRepositoryProvider returns the service provider of the repo for the codebase being instrumented. +func GetRepositoryProvider() string { + return repoProvider +} + +// SetRepositoryProvider sets the service provider of the repo for the codebase being instrumented. +func SetRepositoryProvider(newRepositoryProvider string) { + repoProvider = newRepositoryProvider +} + // GetPushJobName returns the job name to use when the codebase being instrumented is pushing metrics to an OTEL Collector. func GetPushJobName() string { return pushJobName @@ -82,3 +123,20 @@ func GetPushJobURL() string { func SetPushJobURL(newPushJobURL string) { pushJobURL = newPushJobURL } + +func fetchFunctionName(traceID TraceID, spanID SpanID) (FunctionID, error) { + fid, ok := instrumentedSpans[spanKey{tid: traceID, sid: spanID}] + if !ok { + return FunctionID{}, fmt.Errorf("%v,%v is not a known traceID/spanID pair now", traceID, spanID) + } + + return fid, nil +} + +func popFunctionName(traceID TraceID, spanID SpanID) { + delete(instrumentedSpans, spanKey{tid: traceID, sid: spanID}) +} + +func pushFunctionName(traceID TraceID, spanID SpanID, functionID FunctionID) { + instrumentedSpans[spanKey{tid: traceID, sid: spanID}] = functionID +} diff --git a/pkg/autometrics/instrument.go b/pkg/autometrics/instrument.go index 5bc6db7..dac0cec 100644 --- a/pkg/autometrics/instrument.go +++ b/pkg/autometrics/instrument.go @@ -1,6 +1,7 @@ package autometrics import ( + "context" "reflect" "runtime" "strings" @@ -8,7 +9,7 @@ import ( // CallerInfo returns the (method name, module name) of the function that called the function that called this function. // -// It also returns the information about its grandparent. +// It also returns the information about its autometricized grandparent. // // The module name and the parent module names are cropped to their last part, because the generator we use // only has access to the last "package" name in `GOPACKAGE` environment variable. @@ -17,7 +18,7 @@ import ( // then we can lift this artificial limitation here and use the full "module name" from the caller information. // Currently this compromise is the only way to have the documentation links generator creating correct // queries. -func CallerInfo() (callInfo CallInfo) { +func callerInfo(ctx context.Context) (callInfo CallInfo) { programCounters := make([]uintptr, 15) // skip 3 frames to start with: @@ -33,40 +34,46 @@ func CallerInfo() (callInfo CallInfo) { index := strings.LastIndex(functionName, ".") if index == -1 { - callInfo.FuncName = functionName + callInfo.Current.Function = functionName } else { - callInfo.ModuleName = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll( + callInfo.Current.Module = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll( functionName[:index], "(", ""), ")", ""), "*", "") - callInfo.FuncName = functionName[index+1:] + callInfo.Current.Function = functionName[index+1:] } - if !hasParent { - return - } + parent, err := ParentFunctionName(ctx) - // Do the same with the parent - parentFrame, _ := frames.Next() + if err != nil { + // We try to fallback to the parent in the call stack if we don't have the info + if !hasParent { + return + } - parentFunctionName := parentFrame.Function - index = strings.LastIndex(parentFunctionName, ".") + parentFrame, _ := frames.Next() + parentFrameFunctionName := parentFrame.Function + index = strings.LastIndex(parentFrameFunctionName, ".") - if index == -1 { - callInfo.ParentFuncName = parentFunctionName - } else { - moduleIndex := strings.LastIndex(parentFunctionName[:index], ".") - if moduleIndex == -1 { - callInfo.ParentModuleName = parentFunctionName[:index] + if index == -1 { + callInfo.Parent.Function = parentFrameFunctionName } else { - callInfo.ParentModuleName = parentFunctionName[moduleIndex+1 : index] + callInfo.Parent.Module = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll( + parentFrameFunctionName[:index], + "(", ""), + ")", ""), + "*", "") + + callInfo.Parent.Function = functionName[index+1:] } - callInfo.ParentFuncName = parentFunctionName[index+1:] + return } + callInfo.Parent = parent + return } @@ -80,15 +87,15 @@ func ReflectFunctionModuleName(f interface{}) (callInfo CallInfo) { index := strings.LastIndex(functionName, ".") if index == -1 { - callInfo.FuncName = functionName + callInfo.Current.Function = functionName } else { - moduleIndex := strings.LastIndex(functionName[:index], ".") - if moduleIndex == -1 { - callInfo.ModuleName = functionName[:index] - } else { - callInfo.ModuleName = functionName[moduleIndex+1 : index] - } - callInfo.FuncName = functionName[index+1:] + callInfo.Current.Module = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll( + functionName[:index], + "(", ""), + ")", ""), + "*", "") + + callInfo.Current.Function = functionName[index+1:] } return callInfo diff --git a/pkg/autometrics/main.go b/pkg/autometrics/main.go index 1d15db7..a2df5b4 100644 --- a/pkg/autometrics/main.go +++ b/pkg/autometrics/main.go @@ -31,16 +31,26 @@ const ( MiddlewareTraceIDKey = "autometricsTraceID" ) +// FunctionID is a unique identifier for a function (on a per-codebase basis) +type FunctionID struct { + // Function is the name of the function being tracked + Function string + // Module is the name of the module containing the function being tracked, up to (and including) the class name + Module string +} + // CallInfo holds the information about the current function call and its parent names. type CallInfo struct { - // FuncName is name of the function being tracked. - FuncName string - // ModuleName is name of the module of the function being tracked. - ModuleName string - // ParentFuncName is name of the caller of the function being tracked. - ParentFuncName string - // ParentModuleName is name of the module of the caller of the function being tracked. - ParentModuleName string + // Current is the identifier of the function being tracked + Current FunctionID + // Parent is the identifirs of the caller of the function being tracked. + // + // The parent information is only included for autometricized functions. This + // means: + // - if A calls B calls C, + // - only A and C have autometrics annotations, + // then the Caller information when working with C is going to be A, _not_ B + Parent FunctionID } // BuildInfo holds the information about the current build of the instrumented code. @@ -51,8 +61,12 @@ type BuildInfo struct { Version string // Branch is the branch of the build of the codebase. Branch string - // ServiceName is the name of the service + // Service is the name of the service Service string + // RepositoryURL is the URL of the repository containing the code + RepositoryURL string + // RepositoryProvider is the service provider for the repository containing the code + RepositoryProvider string } // PushConfiguration holds the information necessary to push metrics to an OTEL Collector. diff --git a/prometheus/autometrics/instrument.go b/prometheus/autometrics/instrument.go index fac3cd1..9db0e76 100644 --- a/prometheus/autometrics/instrument.go +++ b/prometheus/autometrics/instrument.go @@ -51,10 +51,10 @@ func Instrument(ctx context.Context, err *error) { info := exemplars(ctx) functionCallsCount.With(prometheus.Labels{ - FunctionLabel: callInfo.FuncName, - ModuleLabel: callInfo.ModuleName, - CallerFunctionLabel: callInfo.ParentFuncName, - CallerModuleLabel: callInfo.ParentModuleName, + FunctionLabel: callInfo.Current.Function, + ModuleLabel: callInfo.Current.Module, + CallerFunctionLabel: callInfo.Parent.Function, + CallerModuleLabel: callInfo.Parent.Module, ResultLabel: result, TargetSuccessRateLabel: successObjective, SloNameLabel: sloName, @@ -62,18 +62,13 @@ func Instrument(ctx context.Context, err *error) { CommitLabel: buildInfo.Commit, VersionLabel: buildInfo.Version, ServiceNameLabel: buildInfo.Service, - // REVIEW: This clear mode label is added to make the metrics work when - // pushing metrics to a gravel gateway. To reconsider once - // https://github.com/sinkingpoint/prometheus-gravel-gateway/issues/28 - // is solved - ClearModeLabel: ClearModeFamily, }).(prometheus.ExemplarAdder).AddWithExemplar(1, info) functionCallsDuration.With(prometheus.Labels{ - FunctionLabel: callInfo.FuncName, - ModuleLabel: callInfo.ModuleName, - CallerFunctionLabel: callInfo.ParentFuncName, - CallerModuleLabel: callInfo.ParentModuleName, + FunctionLabel: callInfo.Current.Function, + ModuleLabel: callInfo.Current.Module, + CallerFunctionLabel: callInfo.Parent.Function, + CallerModuleLabel: callInfo.Parent.Module, TargetLatencyLabel: latencyTarget, TargetSuccessRateLabel: latencyObjective, SloNameLabel: sloName, @@ -81,28 +76,18 @@ func Instrument(ctx context.Context, err *error) { CommitLabel: buildInfo.Commit, VersionLabel: buildInfo.Version, ServiceNameLabel: buildInfo.Service, - // REVIEW: This clear mode label is added to make the metrics work when - // pushing metrics to a gravel gateway. To reconsider once - // https://github.com/sinkingpoint/prometheus-gravel-gateway/issues/28 - // is solved - ClearModeLabel: ClearModeFamily, }).(prometheus.ExemplarObserver).ObserveWithExemplar(time.Since(am.GetStartTime(ctx)).Seconds(), info) if am.GetTrackConcurrentCalls(ctx) { functionCallsConcurrent.With(prometheus.Labels{ - FunctionLabel: callInfo.FuncName, - ModuleLabel: callInfo.ModuleName, - CallerFunctionLabel: callInfo.ParentFuncName, - CallerModuleLabel: callInfo.ParentModuleName, + FunctionLabel: callInfo.Current.Function, + ModuleLabel: callInfo.Current.Module, + CallerFunctionLabel: callInfo.Parent.Function, + CallerModuleLabel: callInfo.Parent.Module, BranchLabel: buildInfo.Branch, CommitLabel: buildInfo.Commit, VersionLabel: buildInfo.Version, ServiceNameLabel: buildInfo.Service, - // REVIEW: This clear mode label is added to make the metrics work when - // pushing metrics to a gravel gateway. To reconsider once - // https://github.com/sinkingpoint/prometheus-gravel-gateway/issues/28 - // is solved - ClearModeLabel: ClearModeFamily, }).Add(-1) } @@ -126,6 +111,11 @@ func Instrument(ctx context.Context, err *error) { } }(amCtx) } + + // NOTE: This call means that goroutines that outlive this function as the caller will not have access to parent + // caller information, but hopefully by that point we got all the necessary accesses done. + // If not, it is a convenience we accept to give up to prevent memory usage from exploding + _ = am.PopFunctionName(ctx) } // PreInstrument runs the "before wrappee" part of instrumentation. @@ -137,27 +127,21 @@ func PreInstrument(ctx context.Context) context.Context { return nil } - callInfo := am.CallerInfo() - ctx = am.SetCallInfo(ctx, callInfo) + ctx = am.FillTracingAndCallerInfo(ctx) ctx = am.FillBuildInfo(ctx) - ctx = am.FillTracingInfo(ctx) buildInfo := am.GetBuildInfo(ctx) + callInfo := am.GetCallInfo(ctx) if am.GetTrackConcurrentCalls(ctx) { functionCallsConcurrent.With(prometheus.Labels{ - FunctionLabel: callInfo.FuncName, - ModuleLabel: callInfo.ModuleName, - CallerFunctionLabel: callInfo.ParentFuncName, - CallerModuleLabel: callInfo.ParentModuleName, + FunctionLabel: callInfo.Current.Function, + ModuleLabel: callInfo.Current.Module, + CallerFunctionLabel: callInfo.Parent.Function, + CallerModuleLabel: callInfo.Parent.Module, BranchLabel: buildInfo.Branch, CommitLabel: buildInfo.Commit, VersionLabel: buildInfo.Version, ServiceNameLabel: buildInfo.Service, - // REVIEW: This clear mode label is added to make the metrics work when - // pushing metrics to a gravel gateway. To reconsider once - // https://github.com/sinkingpoint/prometheus-gravel-gateway/issues/28 - // is solved - ClearModeLabel: ClearModeFamily, }).Add(1) } diff --git a/prometheus/autometrics/prometheus.go b/prometheus/autometrics/prometheus.go index 437073e..73414d6 100644 --- a/prometheus/autometrics/prometheus.go +++ b/prometheus/autometrics/prometheus.go @@ -27,6 +27,10 @@ var ( ) const ( + // AutometricsSpecVersion is the version of the specification the library follows + // The specifications can be found in https://github.com/autometrics-dev/autometrics-shared/tree/main/specs + AutometricsSpecVersion = "1.0.0" + // FunctionCallsCountName is the name of the prometheus metric for the counter of calls to specific functions. FunctionCallsCountName = "function_calls_total" // FunctionCallsDurationName is the name of the prometheus metric for the duration histogram of calls to specific functions. @@ -76,15 +80,19 @@ const ( // BranchLabel is the prometheus label that describes the branch of the build of the monitored codebase. BranchLabel = "branch" - // ServiceNameLabel is the prometheus label that describes the name of the service being monitored - ServiceNameLabel = "service_name" + // RepositoryURLLabel is the prometheus label that describes the URL at which the repository containing + // the monitored service can be found + RepositoryURLLabel = "repository_url" + // RepositoryProviderLabel is the prometheus label that describes the service provider for the monitored + // service repository url + RepositoryProviderLabel = "repository_provider" - // ClearModeLabel is the label used by Prometheus Gravel Gateway to deal with aggregation. - ClearModeLabel = "clearmode" + // AutometricsVersionLabel is the prometheus label that describes the version of the Autometrics specification + // the library follows + AutometricsVersionLabel = "autometrics_version" - ClearModeFamily = "family" - ClearModeAggregate = "aggregate" - ClearModeReplace = "replace" + // ServiceNameLabel is the prometheus label that describes the name of the service being monitored + ServiceNameLabel = "service_name" traceIdExemplar = "trace_id" spanIdExemplar = "span_id" @@ -160,22 +168,33 @@ func Init(reg *prometheus.Registry, histogramBuckets []float64, buildInformation autometrics.SetService(buildInformation.Service) } + if repoURL, ok := os.LookupEnv(autometrics.AutometricsRepoURLEnv); ok { + autometrics.SetRepositoryURL(repoURL) + } else if buildInformation.RepositoryURL != "" { + autometrics.SetRepositoryURL(buildInformation.RepositoryURL) + } + if repoProvider, ok := os.LookupEnv(autometrics.AutometricsRepoProviderEnv); ok { + autometrics.SetRepositoryURL(repoProvider) + } else if buildInformation.RepositoryProvider != "" { + autometrics.SetRepositoryURL(buildInformation.RepositoryProvider) + } + functionCallsCount = prometheus.NewCounterVec(prometheus.CounterOpts{ Name: FunctionCallsCountName, - }, []string{FunctionLabel, ModuleLabel, CallerFunctionLabel, CallerModuleLabel, ResultLabel, TargetSuccessRateLabel, SloNameLabel, CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel, ClearModeLabel}) + }, []string{FunctionLabel, ModuleLabel, CallerFunctionLabel, CallerModuleLabel, ResultLabel, TargetSuccessRateLabel, SloNameLabel, CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel}) functionCallsDuration = prometheus.NewHistogramVec(prometheus.HistogramOpts{ Name: FunctionCallsDurationName, Buckets: histogramBuckets, - }, []string{FunctionLabel, ModuleLabel, CallerFunctionLabel, CallerModuleLabel, TargetLatencyLabel, TargetSuccessRateLabel, SloNameLabel, CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel, ClearModeLabel}) + }, []string{FunctionLabel, ModuleLabel, CallerFunctionLabel, CallerModuleLabel, TargetLatencyLabel, TargetSuccessRateLabel, SloNameLabel, CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel}) functionCallsConcurrent = prometheus.NewGaugeVec(prometheus.GaugeOpts{ Name: FunctionCallsConcurrentName, - }, []string{FunctionLabel, ModuleLabel, CallerFunctionLabel, CallerModuleLabel, CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel, ClearModeLabel}) + }, []string{FunctionLabel, ModuleLabel, CallerFunctionLabel, CallerModuleLabel, CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel}) buildInfo = prometheus.NewGaugeVec(prometheus.GaugeOpts{ Name: BuildInfoName, - }, []string{CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel, ClearModeLabel}) + }, []string{CommitLabel, VersionLabel, BranchLabel, ServiceNameLabel, RepositoryURLLabel, RepositoryProviderLabel, AutometricsVersionLabel}) if reg != nil { reg.MustRegister(functionCallsCount) @@ -190,11 +209,13 @@ func Init(reg *prometheus.Registry, histogramBuckets []float64, buildInformation } buildInfo.With(prometheus.Labels{ - CommitLabel: buildInformation.Commit, - VersionLabel: buildInformation.Version, - BranchLabel: buildInformation.Branch, - ServiceNameLabel: autometrics.GetService(), - ClearModeLabel: ClearModeFamily, + CommitLabel: buildInformation.Commit, + VersionLabel: buildInformation.Version, + BranchLabel: buildInformation.Branch, + ServiceNameLabel: autometrics.GetService(), + RepositoryURLLabel: autometrics.GetRepositoryURL(), + RepositoryProviderLabel: autometrics.GetRepositoryProvider(), + AutometricsVersionLabel: AutometricsSpecVersion, }).Set(1) if pusher != nil { @@ -234,7 +255,7 @@ func ForceFlush() error { Collector(functionCallsConcurrent) if err := localPusher. AddContext(ctx); err != nil { - return fmt.Errorf("failed to push metrics to gateway: %w", err) + return fmt.Errorf("pushing metrics to gateway: %w", err) } } } diff --git a/scripts/build_generator b/scripts/build_generator index 8dd5121..652c777 100755 --- a/scripts/build_generator +++ b/scripts/build_generator @@ -4,6 +4,10 @@ set -euo pipefail BUILD_PACK="github.com/autometrics-dev/autometrics-go/internal/build" VERSION=`git describe --tags` +USER=`id -u -n` +DATE=`date -u` SCRIPT_DIR="$( dirname -- "$( readlink -f -- "$0"; )"; )" -go build -v -ldflags="-X '${BUILD_PACK}.Version=${VERSION}'" ${SCRIPT_DIR}/../cmd/autometrics/main.go +echo "Building version ${VERSION} (${USER} @ ${DATE})" + +go build -v -a -ldflags="-X '${BUILD_PACK}.Version=${VERSION}' -X '${BUILD_PACK}.User=${USER}' -X '${BUILD_PACK}.Time=${DATE}'" ${SCRIPT_DIR}/../cmd/autometrics/main.go