diff --git a/.github/workflows/turing.yaml b/.github/workflows/turing.yaml index fcbbb3975..5aa90d092 100644 --- a/.github/workflows/turing.yaml +++ b/.github/workflows/turing.yaml @@ -37,8 +37,8 @@ on: env: ARTIFACT_RETENTION_DAYS: 7 - GO_VERSION: "1.22" - GO_LINT_VERSION: v1.56.2 + GO_VERSION: "1.25" + GO_LINT_VERSION: v2.12.2 CLUSTER_NAME: turing-e2e ISTIO_VERSION: 1.9.9 KNATIVE_VERSION: 1.7.4 @@ -257,7 +257,7 @@ jobs: run: make test - name: Lint code - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v7 with: version: ${{ env.GO_LINT_VERSION }} working-directory: api @@ -292,11 +292,10 @@ jobs: run: make benchmark - name: Lint code - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v7 with: version: ${{ env.GO_LINT_VERSION }} working-directory: engines/router - skip-go-installation: true args: --verbose test-engines-experiment: @@ -318,11 +317,10 @@ jobs: run: make test - name: Lint code - uses: golangci/golangci-lint-action@v2 + uses: golangci/golangci-lint-action@v7 with: version: ${{ env.GO_LINT_VERSION }} working-directory: engines/experiment - skip-go-installation: true args: --verbose test-e2e: diff --git a/.golangci.yml b/.golangci.yml index 151fdea9a..3671e9c39 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,28 +1,49 @@ +version: "2" run: build-tags: - e2e - skip-dirs: - - turing/generated - linters: enable: - bodyclose - - errcheck - gocyclo - - gofmt - - goimports - - gosimple - - govet - - ineffassign - lll - misspell - revive - - staticcheck - - unused - -linters-settings: - gocyclo: - # Min code complexity to report, 30 by default (recommended 10-20) - min-complexity: 25 - lll: - line-length: 120 + settings: + gocyclo: + min-complexity: 25 + lll: + line-length: 120 + staticcheck: + # v1 only ever enabled the `staticcheck` (SA*) and `gosimple` (S1*) linters, never + # `stylecheck` (ST*) or the quickfix suggestions (QF*). v2 merges gosimple into this + # single staticcheck linter, so exclude ST*/QF* here to keep the same check scope + # as before, instead of newly linting the whole codebase against rules it was never + # checked against. + checks: + - all + - -ST* + - -QF* + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - turing/generated + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - goimports + exclusions: + generated: lax + paths: + - turing/generated + - third_party$ + - builtin$ + - examples$ diff --git a/api/.env.development b/api/.env.development index 7822788a1..ca65a2dff 100644 --- a/api/.env.development +++ b/api/.env.development @@ -3,8 +3,12 @@ TURING_DATABASE_USER=turing TURING_DATABASE_PASSWORD=turing TURING_DATABASE_NAME=turing TURING_ROUTER_IMAGE=asia.gcr.io/gcp-project-id/turing-router:latest +# Deprecated: classic Jaeger/Thrift backend. Use TURING_ROUTER_OTEL_* instead unless a +# specific downstream backend still requires Thrift ingestion. TURING_ROUTER_JAEGER_ENABLED=false TURING_ROUTER_JAEGER_COLLECTOR_ENDPOINT= +TURING_ROUTER_OTEL_ENABLED=false +TURING_ROUTER_OTEL_COLLECTOR_ENDPOINT= TURING_ROUTER_FLUENTD_IMAGE=asia.gcr.io/gcp-project-id/fluentd-bigquery:0.0.1 TURING_ROUTER_FLUENTD_FLUSH_INTERVAL_SECONDS=10 TURING_ROUTER_LOG_LEVEL=DEBUG diff --git a/api/Dockerfile b/api/Dockerfile index c1d7940f6..98f8d867a 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -3,7 +3,7 @@ FROM gcr.io/google.com/cloudsdktool/google-cloud-cli:alpine as gke-plugin-builde RUN gcloud components install gke-gcloud-auth-plugin --quiet # Build turing-api binary -FROM golang:1.22-alpine as api-builder +FROM golang:1.25-alpine as api-builder ARG API_BIN_NAME=turing-api ENV GO111MODULE=on \ diff --git a/api/Makefile b/api/Makefile index 778f696af..ea0327a98 100644 --- a/api/Makefile +++ b/api/Makefile @@ -14,7 +14,7 @@ clean: .PHONY: setup setup: @echo "Setting up tools..." - @test -x ${GOPATH}/bin/golangci-lint || go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.2 + @test -x ${GOPATH}/bin/golangci-lint || go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2 @test -x ${GOPATH}/bin/gotest || go install github.com/rakyll/gotest@latest .PHONY: fmt diff --git a/api/api/openapi.bundle.yaml b/api/api/openapi.bundle.yaml index d77a8e746..dd78606e3 100644 --- a/api/api/openapi.bundle.yaml +++ b/api/api/openapi.bundle.yaml @@ -2112,11 +2112,13 @@ components: error: error version: 5 log_config: + otel_enabled: true custom_metrics_enabled: true bigquery_config: batch_load: true table: table service_account_secret: service_account_secret + pyroscope_enabled: true kafka_config: brokers: brokers topic: topic @@ -3704,11 +3706,13 @@ components: type: object RouterVersion_log_config: example: + otel_enabled: true custom_metrics_enabled: true bigquery_config: batch_load: true table: table service_account_secret: service_account_secret + pyroscope_enabled: true kafka_config: brokers: brokers topic: topic @@ -3723,6 +3727,12 @@ components: fiber_debug_log_enabled: type: boolean jaeger_enabled: + description: 'Deprecated: use otel_enabled instead. Will be removed in a + future release.' + type: boolean + otel_enabled: + type: boolean + pyroscope_enabled: type: boolean result_logger_type: $ref: '#/components/schemas/ResultLoggerType' diff --git a/api/api/specs/routers.yaml b/api/api/specs/routers.yaml index e8bce212e..947dbd4c1 100644 --- a/api/api/specs/routers.yaml +++ b/api/api/specs/routers.yaml @@ -573,6 +573,13 @@ components: type: "boolean" jaeger_enabled: type: "boolean" + description: >- + Deprecated: use otel_enabled instead. Will be removed in a + future release. + otel_enabled: + type: "boolean" + pyroscope_enabled: + type: "boolean" result_logger_type: $ref: "#/components/schemas/ResultLoggerType" bigquery_config: diff --git a/api/go.mod b/api/go.mod index ffa1f93da..47c9197ef 100644 --- a/api/go.mod +++ b/api/go.mod @@ -1,6 +1,6 @@ module github.com/caraml-dev/turing/api -go 1.22 +go 1.25 require ( bou.ke/monkey v1.0.2 @@ -23,6 +23,7 @@ require ( github.com/google/go-containerregistry v0.19.0 github.com/gorilla/mux v1.8.0 github.com/gorilla/schema v1.1.0 + github.com/grafana/pyroscope-go v1.2.0 github.com/heptiolabs/healthcheck v0.0.0-20180807145615-6ff867650f40 github.com/mitchellh/copystructure v1.2.0 github.com/mitchellh/mapstructure v1.5.0 @@ -35,6 +36,10 @@ require ( github.com/spf13/viper v1.13.0 github.com/stretchr/testify v1.9.0 github.com/xanzy/go-gitlab v0.32.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 go.uber.org/zap v1.26.0 golang.org/x/oauth2 v0.18.0 google.golang.org/grpc v1.62.0 @@ -61,7 +66,6 @@ require ( cloud.google.com/go/compute/metadata v0.2.3 // indirect cloud.google.com/go/iam v1.1.6 // indirect cloud.google.com/go/storage v1.39.0 // indirect - github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/VividCortex/ewma v1.2.0 // indirect github.com/ajg/form v1.5.1 // indirect @@ -88,6 +92,7 @@ require ( github.com/beorn7/perks v1.0.1 // indirect github.com/blendle/zapdriver v1.3.1 // indirect github.com/buger/jsonparser v1.1.1 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054 // indirect github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect @@ -135,7 +140,8 @@ require ( github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/gax-go/v2 v2.12.2 // indirect github.com/gorilla/websocket v1.5.1 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect @@ -164,7 +170,7 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/kelseyhightower/envconfig v1.4.0 // indirect github.com/kevinburke/ssh_config v1.1.0 // indirect - github.com/klauspost/compress v1.17.4 // indirect + github.com/klauspost/compress v1.17.8 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/lib/pq v1.10.3 // indirect github.com/magiconair/properties v1.8.6 // indirect @@ -207,8 +213,8 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.4.1 // indirect - github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect - github.com/uber/jaeger-lib v2.4.0+incompatible // indirect + github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect + github.com/uber/jaeger-lib v2.0.0+incompatible // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.34.0 // indirect github.com/vbatts/tar-split v0.11.3 // indirect @@ -223,10 +229,11 @@ require ( github.com/zaffka/zap-to-hclog v0.10.6 // indirect go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect - go.opentelemetry.io/otel v1.24.0 // indirect + go.opentelemetry.io/contrib/propagators/b3 v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect go.opentelemetry.io/otel/metric v1.24.0 // indirect go.opentelemetry.io/otel/trace v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.21.0 // indirect diff --git a/api/go.sum b/api/go.sum index e812d041b..7f7c09da3 100644 --- a/api/go.sum +++ b/api/go.sum @@ -43,8 +43,6 @@ github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFD github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/GoogleCloudPlatform/spark-on-k8s-operator v0.0.0-20221025152940-c261df66a006 h1:4DDmvGcwJCBvTOI9JVR9Kr0LsrEthCTpewXmX21oPJI= github.com/GoogleCloudPlatform/spark-on-k8s-operator v0.0.0-20221025152940-c261df66a006/go.mod h1:LOBOhAPsC+SOpFPlfpVG7W0pLTypq5woAtAzQ/LbwoE= -github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= -github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= @@ -60,7 +58,6 @@ github.com/VividCortex/ewma v1.2.0 h1:f58SaIzcDXrSy3kWaHNvuJgJ3Nmz59Zji6XoJR/q1o github.com/VividCortex/ewma v1.2.0/go.mod h1:nz4BbCtbLyFDeC9SUHbtcT5644juEuWfUAUnGx7j5l4= github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= @@ -131,6 +128,8 @@ github.com/caraml-dev/mlp v1.13.2 h1:N3lk+ToQ281duZImQLTQ28uJtmoc9Zkxx1CR94rS15U github.com/caraml-dev/mlp v1.13.2/go.mod h1:9kPooDSYsVu5q/z2K4T9uu08RGyiFNbCAFnQVBMJxOk= github.com/caraml-dev/universal-prediction-interface v0.3.6 h1:G/D4aukfjLECl8armJqFy/R2+0u/f4AiurSFqAo33uQ= github.com/caraml-dev/universal-prediction-interface v0.3.6/go.mod h1:e0qmFOXQxx8HFg5ObYyQO3WVnrqsr5v5JApFmeF7eJo= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= 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= @@ -159,6 +158,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/cockroach-go v0.0.0-20190925194419-606b3d062051/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/containerd/containerd v1.3.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k= github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o= @@ -230,7 +231,6 @@ github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -314,7 +314,6 @@ github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1: github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU= github.com/golang-migrate/migrate/v4 v4.11.0 h1:uqtd0ysK5WyBQ/T1K2uDIooJV0o2Obt6uPwP062DupQ= github.com/golang-migrate/migrate/v4 v4.11.0/go.mod h1:nqbpDbckcYjsCD5I8q5+NI9Tkk7SVcmaF40Ax1eAWhg= -github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -407,9 +406,13 @@ github.com/gorilla/schema v1.1.0 h1:CamqUDOFUBqzrvxuz2vEwo8+SUdwsluFh7IlzJh30LY= github.com/gorilla/schema v1.1.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/grafana/pyroscope-go v1.2.0 h1:aILLKjTj8CS8f/24OPMGPewQSYlhmdQMBmol1d3KGj8= +github.com/grafana/pyroscope-go v1.2.0/go.mod h1:2GHr28Nr05bg2pElS+dDsc98f3JTUh2f6Fz1hWXrqwk= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 h1:6UKoz5ujsI55KNpsJH3UwCq3T8kKbZwNZBNPuTTje8U= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1/go.mod h1:YvJ2f6MplWDhfxiUC3KpyTy76kYUZA4W3pTv/wdKQ9Y= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= @@ -519,7 +522,6 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes= github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= @@ -530,8 +532,8 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= @@ -688,8 +690,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g= +github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs= github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U= github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= @@ -759,10 +761,10 @@ github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8= github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/uber/jaeger-client-go v2.25.0+incompatible h1:IxcNZ7WRY1Y3G4poYlx24szfsn/3LvK9QHCq9oQw8+U= -github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-lib v2.4.0+incompatible h1:fY7QsGQWiCt8pajv4r7JEvmATdCVaWxXbjwyYwsNaLQ= -github.com/uber/jaeger-lib v2.4.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= +github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-lib v2.0.0+incompatible h1:iMSCV0rmXEogjNWPh2D0xk9YVKvrtGoHJNe9ebLu/pw= +github.com/uber/jaeger-lib v2.0.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= @@ -815,13 +817,23 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.4 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= +go.opentelemetry.io/contrib/propagators/b3 v1.24.0 h1:n4xwCdTx3pZqZs2CjS/CUZAs03y3dZcGhC/FepKtEUY= +go.opentelemetry.io/contrib/propagators/b3 v1.24.0/go.mod h1:k5wRxKRU2uXx2F8uNJ4TaonuEO/V7/5xoz7kdsDACT8= go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -864,16 +876,12 @@ golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0 golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200213203834-85f925bdd4d0/go.mod h1:IX6Eufr4L0ErOUlzqX/aFlHqsiKZRbV42Kb69e9VsTE= -golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -1046,12 +1054,10 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/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-20190206041539-40960b6deb8e/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-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1097,10 +1103,6 @@ golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSm golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= -gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1320,7 +1322,6 @@ moul.io/http2curl/v2 v2.3.0 h1:9r3JfDzWPcbIklMOs2TnIFzDYvfAZvjeavG6EzP7jYs= moul.io/http2curl/v2 v2.3.0/go.mod h1:RW4hyBjTWSYDOxapodpNEtX0g5Eb16sxklBqmd2RHcE= mvdan.cc/xurls/v2 v2.2.0 h1:NSZPykBXJFCetGZykLAxaL6SIpvbVy/UFEniIfHAa8A= mvdan.cc/xurls/v2 v2.2.0/go.mod h1:EV1RMtya9D6G5DMYPGD8zTQzaHet6Jh8gFlRgGRJeO8= -rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= diff --git a/api/turing/api/base_controller.go b/api/turing/api/base_controller.go index 01cc7d95d..835c4c0a4 100644 --- a/api/turing/api/base_controller.go +++ b/api/turing/api/base_controller.go @@ -49,7 +49,7 @@ func (c BaseController) ParseVars(dst interface{}, vars RequestVars) error { return nil } -func (c BaseController) getProjectFromRequestVars(vars RequestVars) (project *mlp.Project, error *Response) { +func (c BaseController) getProjectFromRequestVars(vars RequestVars) (project *mlp.Project, errResponse *Response) { id, err := getIDFromVars(vars, "project_id") if err != nil { return nil, BadRequest("invalid project id", err.Error()) @@ -61,7 +61,7 @@ func (c BaseController) getProjectFromRequestVars(vars RequestVars) (project *ml return project, nil } -func (c BaseController) getRouterFromRequestVars(vars RequestVars) (router *models.Router, error *Response) { +func (c BaseController) getRouterFromRequestVars(vars RequestVars) (router *models.Router, errResponse *Response) { id, err := getIDFromVars(vars, "router_id") if err != nil { return nil, BadRequest("invalid router id", err.Error()) @@ -75,7 +75,7 @@ func (c BaseController) getRouterFromRequestVars(vars RequestVars) (router *mode func (c BaseController) getRouterVersionFromRequestVars( vars RequestVars, -) (routerVersion *models.RouterVersion, error *Response) { +) (routerVersion *models.RouterVersion, errResponse *Response) { routerID, err := getIDFromVars(vars, "router_id") if err != nil { return nil, BadRequest("invalid router id", err.Error()) diff --git a/api/turing/api/request/request.go b/api/turing/api/request/request.go index c43cf3f1b..13ca75aaf 100644 --- a/api/turing/api/request/request.go +++ b/api/turing/api/request/request.go @@ -158,7 +158,9 @@ func (r RouterConfig) BuildRouterVersion( LogLevel: routerConfig.LogLevel(defaults.LogLevel), CustomMetricsEnabled: defaults.CustomMetricsEnabled, FiberDebugLogEnabled: defaults.FiberDebugLogEnabled, - JaegerEnabled: defaults.JaegerEnabled, + JaegerEnabled: defaults.JaegerEnabled, //nolint:staticcheck + OtelEnabled: defaults.OtelEnabled, + PyroscopeEnabled: defaults.PyroscopeEnabled, ResultLoggerType: r.LogConfig.ResultLoggerType, }, } diff --git a/api/turing/api/request/request_test.go b/api/turing/api/request/request_test.go index 8c668f764..d166753b3 100644 --- a/api/turing/api/request/request_test.go +++ b/api/turing/api/request/request_test.go @@ -357,6 +357,9 @@ func TestRequestBuildRouterVersionWithDefaultConfig(t *testing.T) { CustomMetricsEnabled: true, JaegerEnabled: true, JaegerCollectorEndpoint: "jaegerendpoint", + OtelEnabled: true, + OtelCollectorEndpoint: "otelendpoint", + PyroscopeEnabled: true, LogLevel: "DEBUG", FluentdConfig: &config.FluentdConfig{ Image: "fluentdimage", @@ -404,6 +407,8 @@ func TestRequestBuildRouterVersionWithDefaultConfig(t *testing.T) { CustomMetricsEnabled: true, FiberDebugLogEnabled: true, JaegerEnabled: true, + OtelEnabled: true, + PyroscopeEnabled: true, ResultLoggerType: models.BigQueryLogger, BigQueryConfig: &models.BigQueryConfig{ Table: "project.dataset.table", diff --git a/api/turing/cluster/controller.go b/api/turing/cluster/controller.go index 1757cb07e..5e1efffb9 100644 --- a/api/turing/cluster/controller.go +++ b/api/turing/cluster/controller.go @@ -39,6 +39,7 @@ import ( _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" "github.com/caraml-dev/turing/api/turing/config" + logger "github.com/caraml-dev/turing/api/turing/log" ) var ErrNamespaceAlreadyExists = errors.New("namespace already exists") @@ -258,9 +259,6 @@ func (c *controller) DeleteConfigMap(ctx context.Context, name string, namespace // Deploy creates / updates a Kubernetes/Knative service with the given specs func (c *controller) DeployKnativeService(ctx context.Context, svcConf *KnativeService) error { - var existingSvc *knservingv1.Service - var err error - // Build the deployment specs desiredSvc, err := svcConf.BuildKnativeServiceConfig() if err != nil { @@ -270,39 +268,107 @@ func (c *controller) DeployKnativeService(ctx context.Context, svcConf *KnativeS // Init knative ServicesGetter services := c.knServingClient.Services(svcConf.Namespace) - // Check if service already exists. If exists, update it. If not, create. - existingSvc, err = services.Get(ctx, svcConf.Name, metav1.GetOptions{}) + // Some clusters' Knative Serving installations reject env[].valueFrom.fieldRef in the + // container spec outright (the alpha kubernetes.podspec-fieldref feature gate is disabled by + // default). Rather than requiring every cluster to opt into that gate, or requiring a + // separate permission to read Knative's own feature-flag ConfigMap, probe for it with a + // dry-run of this exact request first, and silently drop those env vars if rejected. + if hasFieldRefEnvVars(desiredSvc) { + if err := applyKnativeService(ctx, services, svcConf.Name, desiredSvc, true); err != nil { + if !isFieldRefRejection(err) { + return err + } + logger.Warnf( + "cluster rejected env[].valueFrom.fieldRef for Knative service %s/%s (%s); "+ + "deploying without it", + svcConf.Namespace, svcConf.Name, err.Error(), + ) + stripFieldRefEnvVars(desiredSvc) + } + } + + if err := applyKnativeService(ctx, services, svcConf.Name, desiredSvc, false); err != nil { + return err + } + + // Wait until service ready and return any errors + return c.waitKnativeServiceReady(ctx, svcConf.Name, svcConf.Namespace) +} + +// applyKnativeService creates or updates the Knative service named svcName to match desiredSvc. +// When dryRun is true, no changes are persisted -- this only exercises the API server's admission +// chain, to test whether desiredSvc as given would be accepted. +func applyKnativeService( + ctx context.Context, + services knservingclient.ServiceInterface, + svcName string, + desiredSvc *knservingv1.Service, + dryRun bool, +) error { + var dryRunOpt []string + if dryRun { + dryRunOpt = []string{metav1.DryRunAll} + } + + existingSvc, err := services.Get(ctx, svcName, metav1.GetOptions{}) if err != nil { - if k8serrors.IsNotFound(err) { - // Create new service - _, err = services.Create(ctx, desiredSvc, metav1.CreateOptions{}) - } else { + if !k8serrors.IsNotFound(err) { // Unexpected error, return it return err } - } else { - // Check for differences between current and new specs - if !knServiceSemanticEquals(desiredSvc, existingSvc) { - _, err = kmp.SafeDiff( - desiredSvc.Spec.ConfigurationSpec, - existingSvc.Spec.ConfigurationSpec, - ) - if err != nil { - return fmt.Errorf("Failed to diff Knative Service: %v", err) + // Create new service + _, err = services.Create(ctx, desiredSvc, metav1.CreateOptions{DryRun: dryRunOpt}) + return err + } + + // Check for differences between current and new specs + if knServiceSemanticEquals(desiredSvc, existingSvc) { + return nil + } + if _, err := kmp.SafeDiff(desiredSvc.Spec.ConfigurationSpec, existingSvc.Spec.ConfigurationSpec); err != nil { + return fmt.Errorf("Failed to diff Knative Service: %v", err) + } + // Update the existing service with the new config + existingSvc.Spec.ConfigurationSpec = desiredSvc.Spec.ConfigurationSpec + existingSvc.ObjectMeta.Labels = desiredSvc.ObjectMeta.Labels + _, err = services.Update(ctx, existingSvc, metav1.UpdateOptions{DryRun: dryRunOpt}) + return err +} + +// hasFieldRefEnvVars reports whether any container in the service's pod spec sets an env var via +// the Kubernetes downward API (env[].valueFrom.fieldRef). +func hasFieldRefEnvVars(svc *knservingv1.Service) bool { + for _, container := range svc.Spec.ConfigurationSpec.Template.Spec.Containers { + for _, env := range container.Env { + if env.ValueFrom != nil && env.ValueFrom.FieldRef != nil { + return true } - // Update the existing service with the new config - existingSvc.Spec.ConfigurationSpec = desiredSvc.Spec.ConfigurationSpec - existingSvc.ObjectMeta.Labels = desiredSvc.ObjectMeta.Labels - _, err = services.Update(ctx, existingSvc, metav1.UpdateOptions{}) } } + return false +} - if err != nil { - return err +// stripFieldRefEnvVars removes, in place, every env[].valueFrom.fieldRef entry from the service's +// containers. +func stripFieldRefEnvVars(svc *knservingv1.Service) { + containers := svc.Spec.ConfigurationSpec.Template.Spec.Containers + for i := range containers { + filtered := containers[i].Env[:0] + for _, env := range containers[i].Env { + if env.ValueFrom != nil && env.ValueFrom.FieldRef != nil { + continue + } + filtered = append(filtered, env) + } + containers[i].Env = filtered } +} - // Wait until service ready and return any errors - return c.waitKnativeServiceReady(ctx, svcConf.Name, svcConf.Namespace) +// isFieldRefRejection reports whether err is the admission rejection Knative's Revision webhook +// returns for env[].valueFrom.fieldRef when the cluster's kubernetes.podspec-fieldref feature +// gate is disabled (the default). +func isFieldRefRejection(err error) bool { + return err != nil && strings.Contains(err.Error(), "valueFrom.fieldRef") } // Delete removes the Kubernetes/Knative service and all related artifacts diff --git a/api/turing/cluster/controller_test.go b/api/turing/cluster/controller_test.go index 793e6270d..7dfcee0f3 100644 --- a/api/turing/cluster/controller_test.go +++ b/api/turing/cluster/controller_test.go @@ -191,6 +191,194 @@ func TestDeployKnativeService(t *testing.T) { } } +func TestDeployKnativeServiceFieldRefRejectedFallsBackWithoutIt(t *testing.T) { + testName, testNamespace := "test-name", "test-namespace" + + svcWithFieldRef := &knservingv1.Service{ + ObjectMeta: metav1.ObjectMeta{Name: testName}, + Spec: knservingv1.ServiceSpec{ + ConfigurationSpec: knservingv1.ConfigurationSpec{ + Template: knservingv1.RevisionTemplateSpec{ + Spec: knservingv1.RevisionSpec{ + PodSpec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Env: []corev1.EnvVar{ + {Name: "APP_NAME", Value: "test"}, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + } + + svcConf := &KnativeService{ + BaseService: &BaseService{ + Name: testName, + Namespace: testNamespace, + }, + } + + getReady := func(_ k8stesting.Action) (bool, runtime.Object, error) { + return true, &knservingv1.Service{ + ObjectMeta: metav1.ObjectMeta{Name: testName}, + Status: knservingv1.ServiceStatus{ + Status: duckv1.Status{ + Conditions: duckv1.Conditions{ + apis.Condition{Type: apis.ConditionReady, Status: corev1.ConditionTrue}, + }, + }, + }, + }, nil + } + + fieldRefRejection := errors.New( + `admission webhook "validation.webhook.serving.knative.dev" denied the request: ` + + `validation failed: must not set the field(s): ` + + `spec.template.spec.containers[0].env[1].valueFrom.fieldRef`, + ) + + createCallCount := 0 + + cs := knservingclientset.NewSimpleClientset() + cs.PrependReactor(reactorVerbs.Get, knativeServicesResource, + func(_ k8stesting.Action) (bool, runtime.Object, error) { + return true, nil, k8serrors.NewNotFound(schema.GroupResource{}, testName) + }) + cs.PrependReactor(reactorVerbs.Create, knativeServicesResource, + func(action k8stesting.Action) (bool, runtime.Object, error) { + createCallCount++ + created := action.(k8stesting.CreateAction).GetObject().(*knservingv1.Service) + + if createCallCount == 1 { + // First (dry-run) attempt: still carries the fieldRef env var; cluster rejects it. + assert.True(t, hasFieldRefEnvVars(created), + "expected first Create attempt to still include the fieldRef env var") + return true, nil, fieldRefRejection + } + // Second (real) attempt, after stripping: must no longer include it. + assert.False(t, hasFieldRefEnvVars(created), + "expected fieldRef env var to be stripped before the real Create") + cs.PrependReactor(reactorVerbs.Get, knativeServicesResource, getReady) + return true, created, nil + }) + + monkey.PatchInstanceMethod( + reflect.TypeOf(svcConf), + "BuildKnativeServiceConfig", + func(*KnativeService) (*knservingv1.Service, error) { + return svcWithFieldRef.DeepCopy(), nil + }) + defer monkey.UnpatchAll() + + c := &controller{knServingClient: cs.ServingV1()} + + ctx, cancel := context.WithTimeout(context.Background(), contextTimeoutDuration) + defer cancel() + + err := c.DeployKnativeService(ctx, svcConf) + + assert.NoError(t, err) + assert.Equal(t, 2, createCallCount, "expected exactly two Create attempts: dry-run, then real") +} + +func TestHasFieldRefEnvVars(t *testing.T) { + withFieldRef := &knservingv1.Service{Spec: knservingv1.ServiceSpec{ + ConfigurationSpec: knservingv1.ConfigurationSpec{ + Template: knservingv1.RevisionTemplateSpec{ + Spec: knservingv1.RevisionSpec{ + PodSpec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Env: []corev1.EnvVar{ + {Name: "APP_NAME", Value: "test"}, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }} + withoutFieldRef := &knservingv1.Service{Spec: knservingv1.ServiceSpec{ + ConfigurationSpec: knservingv1.ConfigurationSpec{ + Template: knservingv1.RevisionTemplateSpec{ + Spec: knservingv1.RevisionSpec{ + PodSpec: corev1.PodSpec{ + Containers: []corev1.Container{ + {Env: []corev1.EnvVar{{Name: "APP_NAME", Value: "test"}}}, + }, + }, + }, + }, + }, + }} + + assert.True(t, hasFieldRefEnvVars(withFieldRef)) + assert.False(t, hasFieldRefEnvVars(withoutFieldRef)) +} + +func TestStripFieldRefEnvVars(t *testing.T) { + svc := &knservingv1.Service{Spec: knservingv1.ServiceSpec{ + ConfigurationSpec: knservingv1.ConfigurationSpec{ + Template: knservingv1.RevisionTemplateSpec{ + Spec: knservingv1.RevisionSpec{ + PodSpec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Env: []corev1.EnvVar{ + {Name: "APP_NAME", Value: "test"}, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + { + Name: "POD_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }} + + stripFieldRefEnvVars(svc) + + assert.Equal(t, []corev1.EnvVar{{Name: "APP_NAME", Value: "test"}}, + svc.Spec.ConfigurationSpec.Template.Spec.Containers[0].Env) +} + +func TestIsFieldRefRejection(t *testing.T) { + assert.True(t, isFieldRefRejection(errors.New( + `admission webhook "validation.webhook.serving.knative.dev" denied the request: `+ + `validation failed: must not set the field(s): `+ + `spec.template.spec.containers[0].env[1].valueFrom.fieldRef`))) + assert.False(t, isFieldRefRejection(errors.New("some other unrelated error"))) + assert.False(t, isFieldRefRejection(nil)) +} + func TestDeployKubernetesService(t *testing.T) { testName, testNamespace := "test-name", "test-namespace" statefulSetResourceItem := schema.GroupVersionResource{ diff --git a/api/turing/cluster/servicebuilder/router.go b/api/turing/cluster/servicebuilder/router.go index d7d69d118..0adf9fe87 100644 --- a/api/turing/cluster/servicebuilder/router.go +++ b/api/turing/cluster/servicebuilder/router.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/url" + "sort" "strconv" "strings" @@ -25,18 +26,28 @@ import ( // Define env var names for the router const ( - envAppName = "APP_NAME" - envAppEnvironment = "APP_ENVIRONMENT" - envRouterTimeout = "ROUTER_TIMEOUT" - envEnricherEndpoint = "ENRICHER_ENDPOINT" - envEnricherTimeout = "ENRICHER_TIMEOUT" - envEnsemblerEndpoint = "ENSEMBLER_ENDPOINT" - envEnsemblerTimeout = "ENSEMBLER_TIMEOUT" - envLogLevel = "APP_LOGLEVEL" - envFiberDebugLog = "APP_FIBER_DEBUG_LOG" - envCustomMetrics = "APP_CUSTOM_METRICS" - envJaegerEnabled = "APP_JAEGER_ENABLED" + envAppName = "APP_NAME" + envAppEnvironment = "APP_ENVIRONMENT" + envRouterTimeout = "ROUTER_TIMEOUT" + envEnricherEndpoint = "ENRICHER_ENDPOINT" + envEnricherTimeout = "ENRICHER_TIMEOUT" + envEnsemblerEndpoint = "ENSEMBLER_ENDPOINT" + envEnsemblerTimeout = "ENSEMBLER_TIMEOUT" + envLogLevel = "APP_LOGLEVEL" + envFiberDebugLog = "APP_FIBER_DEBUG_LOG" + envCustomMetrics = "APP_CUSTOM_METRICS" + // Deprecated: use envOtel* instead. + envJaegerEnabled = "APP_JAEGER_ENABLED" + // Deprecated: use envOtel* instead. envJaegerEndpoint = "APP_JAEGER_COLLECTOR_ENDPOINT" + envOtelEnabled = "APP_OTEL_ENABLED" + envOtelEndpoint = "APP_OTEL_COLLECTOR_ENDPOINT" + envOtelSamplingRatio = "APP_OTEL_SAMPLING_RATIO" + envPyroscopeEnabled = "APP_PYROSCOPE_ENABLED" + envPyroscopeServerAddress = "APP_PYROSCOPE_SERVER_ADDRESS" + envPyroscopeHTTPHeaders = "APP_PYROSCOPE_HTTP_HEADERS" + envPyroscopeCustomTags = "APP_PYROSCOPE_CUSTOM_TAGS" + envPyroscopeIncludePodTags = "APP_PYROSCOPE_INCLUDE_POD_TAGS" envSentryEnabled = "APP_SENTRY_ENABLED" envSentryDSN = "APP_SENTRY_DSN" envResultLogger = "APP_RESULT_LOGGER" @@ -58,6 +69,11 @@ const ( envExpGoogleApplicationCredentials = "GOOGLE_APPLICATION_CREDENTIALS_EXPERIMENT_ENGINE" envPluginName = "PLUGIN_NAME" envPluginsDir = "PLUGINS_DIR" + // envPodName and envPodNamespace are set via the Kubernetes downward API so the router + // can tag its Pyroscope profiles with the identity of the individual pod, since a router + // deployment can run multiple replicas behind the same APP_NAME. + envPodName = "POD_NAME" + envPodNamespace = "POD_NAMESPACE" ) // Router service constants @@ -202,6 +218,22 @@ func (sb *clusterSvcBuilder) GetRouterServiceName(routerVersion *models.RouterVe return GetComponentName(routerVersion, ComponentTypes.Router) } +// formatMapEnvVar serializes a map into the "Key1:Val1,Key2:Val2" format expected by the +// router's envconfig-based map decoding, with keys sorted for deterministic output. +func formatMapEnvVar(m map[string]string) string { + keys := make([]string, 0, len(m)) + for k := range m { + keys = append(keys, k) + } + sort.Strings(keys) + + pairs := make([]string, 0, len(keys)) + for _, k := range keys { + pairs = append(pairs, fmt.Sprintf("%s:%s", k, m[k])) + } + return strings.Join(pairs, ",") +} + func (sb *clusterSvcBuilder) buildRouterEnvs( namespace string, environmentType string, @@ -212,17 +244,35 @@ func (sb *clusterSvcBuilder) buildRouterEnvs( ) ([]corev1.EnvVar, error) { envs := sb.getEnvVars(ver.ResourceRequest, nil, nil, "") - // Add app name, router timeout, jaeger collector + // Add app name, router timeout, jaeger collector (deprecated) and otel collector envs = mergeEnvVars(envs, []corev1.EnvVar{ {Name: envAppName, Value: fmt.Sprintf("%s-%d.%s", ver.Router.Name, ver.Version, namespace)}, {Name: envAppEnvironment, Value: environmentType}, {Name: envRouterTimeout, Value: ver.Timeout}, - {Name: envJaegerEndpoint, Value: routerDefaults.JaegerCollectorEndpoint}, + {Name: envJaegerEndpoint, Value: routerDefaults.JaegerCollectorEndpoint}, //nolint:staticcheck + {Name: envOtelEndpoint, Value: routerDefaults.OtelCollectorEndpoint}, + {Name: envOtelSamplingRatio, Value: strconv.FormatFloat(routerDefaults.OtelSamplingRatio, 'f', -1, 64)}, + {Name: envPyroscopeServerAddress, Value: routerDefaults.PyroscopeServerAddress}, + {Name: envPyroscopeHTTPHeaders, Value: formatMapEnvVar(routerDefaults.PyroscopeHTTPHeaders)}, + {Name: envPyroscopeCustomTags, Value: formatMapEnvVar(routerDefaults.PyroscopeCustomTags)}, + {Name: envPyroscopeIncludePodTags, Value: strconv.FormatBool(routerDefaults.PyroscopeIncludePodTags)}, {Name: envRouterConfigFile, Value: routerConfigMapMountPath + routerConfigFileName}, {Name: envRouterProtocol, Value: string(ver.Protocol)}, {Name: envSentryEnabled, Value: strconv.FormatBool(sentryEnabled)}, {Name: envSentryDSN, Value: sentryDSN}, + { + Name: envPodName, + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + { + Name: envPodNamespace, + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + }, + }, }) // Add enricher / ensembler related env vars, if enabled @@ -259,7 +309,9 @@ func (sb *clusterSvcBuilder) buildRouterEnvs( envs = mergeEnvVars(envs, []corev1.EnvVar{ {Name: envLogLevel, Value: string(logConfig.LogLevel)}, {Name: envCustomMetrics, Value: strconv.FormatBool(logConfig.CustomMetricsEnabled)}, - {Name: envJaegerEnabled, Value: strconv.FormatBool(logConfig.JaegerEnabled)}, + {Name: envJaegerEnabled, Value: strconv.FormatBool(logConfig.JaegerEnabled)}, //nolint:staticcheck + {Name: envOtelEnabled, Value: strconv.FormatBool(logConfig.OtelEnabled)}, + {Name: envPyroscopeEnabled, Value: strconv.FormatBool(logConfig.PyroscopeEnabled)}, {Name: envResultLogger, Value: string(logConfig.ResultLoggerType)}, {Name: envFiberDebugLog, Value: strconv.FormatBool(logConfig.FiberDebugLogEnabled)}, }) @@ -607,8 +659,7 @@ func buildFiberConfigMap( } if ver.Ensembler != nil && ver.Ensembler.Type == models.EnsemblerStandardType { - if ver.Ensembler.StandardConfig.ExperimentMappings != nil && - len(ver.Ensembler.StandardConfig.ExperimentMappings) != 0 { + if len(ver.Ensembler.StandardConfig.ExperimentMappings) != 0 { propsMap["experiment_mappings"] = ver.Ensembler.StandardConfig.ExperimentMappings } if ver.Ensembler.StandardConfig.RouteNamePath != "" { @@ -631,7 +682,7 @@ func buildFiberConfigMap( // if the version is configured with traffic splitting rules on it, // then define root-level fiber component as a lazy router with // a traffic-splitting strategy based on these rules - if ver.TrafficRules != nil && len(ver.TrafficRules) > 0 { + if len(ver.TrafficRules) > 0 { // TrafficRule struct used requires the name and conditions field to be specified. But // Default Traffic Rule has no name and a hardcoded name can be used instead since // the name field is not used for traffic splitting strategy. Likewise, an empty slice diff --git a/api/turing/cluster/servicebuilder/router_test.go b/api/turing/cluster/servicebuilder/router_test.go index 773f5ee97..b4f0d9152 100644 --- a/api/turing/cluster/servicebuilder/router_test.go +++ b/api/turing/cluster/servicebuilder/router_test.go @@ -124,13 +124,33 @@ func TestNewRouterService(t *testing.T) { {Name: "APP_ENVIRONMENT", Value: "test-env"}, {Name: "ROUTER_TIMEOUT", Value: "5s"}, {Name: "APP_JAEGER_COLLECTOR_ENDPOINT", Value: "jaeger-endpoint"}, + {Name: "APP_OTEL_COLLECTOR_ENDPOINT", Value: "otel-endpoint"}, + {Name: "APP_OTEL_SAMPLING_RATIO", Value: "0"}, + {Name: "APP_PYROSCOPE_SERVER_ADDRESS", Value: "pyroscope-address"}, + {Name: "APP_PYROSCOPE_HTTP_HEADERS", Value: ""}, + {Name: "APP_PYROSCOPE_CUSTOM_TAGS", Value: ""}, + {Name: "APP_PYROSCOPE_INCLUDE_POD_TAGS", Value: "true"}, {Name: "ROUTER_CONFIG_FILE", Value: "/app/config/fiber.yml"}, {Name: "ROUTER_PROTOCOL", Value: string(routerConfig.HTTP)}, {Name: "APP_SENTRY_ENABLED", Value: "true"}, {Name: "APP_SENTRY_DSN", Value: "sentry-dsn"}, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + { + Name: "POD_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + }, + }, {Name: "APP_LOGLEVEL", Value: "INFO"}, {Name: "APP_CUSTOM_METRICS", Value: "false"}, {Name: "APP_JAEGER_ENABLED", Value: "false"}, + {Name: "APP_OTEL_ENABLED", Value: "false"}, + {Name: "APP_PYROSCOPE_ENABLED", Value: "false"}, {Name: "APP_RESULT_LOGGER", Value: "bigquery"}, {Name: "APP_FIBER_DEBUG_LOG", Value: "false"}, {Name: "APP_GCP_PROJECT", Value: "gcp-project-id"}, @@ -227,13 +247,33 @@ func TestNewRouterService(t *testing.T) { {Name: "APP_ENVIRONMENT", Value: "test-env"}, {Name: "ROUTER_TIMEOUT", Value: "5s"}, {Name: "APP_JAEGER_COLLECTOR_ENDPOINT", Value: "jaeger-endpoint"}, + {Name: "APP_OTEL_COLLECTOR_ENDPOINT", Value: "otel-endpoint"}, + {Name: "APP_OTEL_SAMPLING_RATIO", Value: "0"}, + {Name: "APP_PYROSCOPE_SERVER_ADDRESS", Value: "pyroscope-address"}, + {Name: "APP_PYROSCOPE_HTTP_HEADERS", Value: ""}, + {Name: "APP_PYROSCOPE_CUSTOM_TAGS", Value: ""}, + {Name: "APP_PYROSCOPE_INCLUDE_POD_TAGS", Value: "true"}, {Name: "ROUTER_CONFIG_FILE", Value: "/app/config/fiber.yml"}, {Name: "ROUTER_PROTOCOL", Value: string(routerConfig.UPI)}, {Name: "APP_SENTRY_ENABLED", Value: "true"}, {Name: "APP_SENTRY_DSN", Value: "sentry-dsn"}, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + { + Name: "POD_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + }, + }, {Name: "APP_LOGLEVEL", Value: "INFO"}, {Name: "APP_CUSTOM_METRICS", Value: "false"}, {Name: "APP_JAEGER_ENABLED", Value: "false"}, + {Name: "APP_OTEL_ENABLED", Value: "false"}, + {Name: "APP_PYROSCOPE_ENABLED", Value: "false"}, {Name: "APP_RESULT_LOGGER", Value: "bigquery"}, {Name: "APP_FIBER_DEBUG_LOG", Value: "false"}, {Name: "APP_GCP_PROJECT", Value: "gcp-project-id"}, @@ -329,10 +369,28 @@ func TestNewRouterService(t *testing.T) { {Name: "APP_ENVIRONMENT", Value: "test-env"}, {Name: "ROUTER_TIMEOUT", Value: "5s"}, {Name: "APP_JAEGER_COLLECTOR_ENDPOINT", Value: "jaeger-endpoint"}, + {Name: "APP_OTEL_COLLECTOR_ENDPOINT", Value: "otel-endpoint"}, + {Name: "APP_OTEL_SAMPLING_RATIO", Value: "0"}, + {Name: "APP_PYROSCOPE_SERVER_ADDRESS", Value: "pyroscope-address"}, + {Name: "APP_PYROSCOPE_HTTP_HEADERS", Value: ""}, + {Name: "APP_PYROSCOPE_CUSTOM_TAGS", Value: ""}, + {Name: "APP_PYROSCOPE_INCLUDE_POD_TAGS", Value: "true"}, {Name: "ROUTER_CONFIG_FILE", Value: "/app/config/fiber.yml"}, {Name: "ROUTER_PROTOCOL", Value: string(routerConfig.HTTP)}, {Name: "APP_SENTRY_ENABLED", Value: "true"}, {Name: "APP_SENTRY_DSN", Value: "sentry-dsn"}, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + { + Name: "POD_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + }, + }, {Name: "ENRICHER_ENDPOINT", Value: enrEndpoint}, {Name: "ENRICHER_TIMEOUT", Value: "2s"}, {Name: "ENSEMBLER_ENDPOINT", Value: ensEndpoint}, @@ -340,6 +398,8 @@ func TestNewRouterService(t *testing.T) { {Name: "APP_LOGLEVEL", Value: "INFO"}, {Name: "APP_CUSTOM_METRICS", Value: "false"}, {Name: "APP_JAEGER_ENABLED", Value: "false"}, + {Name: "APP_OTEL_ENABLED", Value: "false"}, + {Name: "APP_PYROSCOPE_ENABLED", Value: "false"}, {Name: "APP_RESULT_LOGGER", Value: "bigquery"}, {Name: "APP_FIBER_DEBUG_LOG", Value: "false"}, {Name: "APP_GCP_PROJECT", Value: "gcp-project-id"}, @@ -438,13 +498,33 @@ func TestNewRouterService(t *testing.T) { {Name: "APP_ENVIRONMENT", Value: "test-env"}, {Name: "ROUTER_TIMEOUT", Value: "5s"}, {Name: "APP_JAEGER_COLLECTOR_ENDPOINT", Value: "jaeger-endpoint"}, + {Name: "APP_OTEL_COLLECTOR_ENDPOINT", Value: "otel-endpoint"}, + {Name: "APP_OTEL_SAMPLING_RATIO", Value: "0"}, + {Name: "APP_PYROSCOPE_SERVER_ADDRESS", Value: "pyroscope-address"}, + {Name: "APP_PYROSCOPE_HTTP_HEADERS", Value: ""}, + {Name: "APP_PYROSCOPE_CUSTOM_TAGS", Value: ""}, + {Name: "APP_PYROSCOPE_INCLUDE_POD_TAGS", Value: "true"}, {Name: "ROUTER_CONFIG_FILE", Value: "/app/config/fiber.yml"}, {Name: "ROUTER_PROTOCOL", Value: string(routerConfig.HTTP)}, {Name: "APP_SENTRY_ENABLED", Value: "true"}, {Name: "APP_SENTRY_DSN", Value: "sentry-dsn"}, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + { + Name: "POD_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + }, + }, {Name: "APP_LOGLEVEL", Value: "INFO"}, {Name: "APP_CUSTOM_METRICS", Value: "false"}, {Name: "APP_JAEGER_ENABLED", Value: "false"}, + {Name: "APP_OTEL_ENABLED", Value: "false"}, + {Name: "APP_PYROSCOPE_ENABLED", Value: "false"}, {Name: "APP_RESULT_LOGGER", Value: "bigquery"}, {Name: "APP_FIBER_DEBUG_LOG", Value: "false"}, {Name: "APP_GCP_PROJECT", Value: "gcp-project-id"}, @@ -539,13 +619,33 @@ func TestNewRouterService(t *testing.T) { {Name: "APP_ENVIRONMENT", Value: "test-env"}, {Name: "ROUTER_TIMEOUT", Value: "5s"}, {Name: "APP_JAEGER_COLLECTOR_ENDPOINT", Value: "jaeger-endpoint"}, + {Name: "APP_OTEL_COLLECTOR_ENDPOINT", Value: "otel-endpoint"}, + {Name: "APP_OTEL_SAMPLING_RATIO", Value: "0"}, + {Name: "APP_PYROSCOPE_SERVER_ADDRESS", Value: "pyroscope-address"}, + {Name: "APP_PYROSCOPE_HTTP_HEADERS", Value: ""}, + {Name: "APP_PYROSCOPE_CUSTOM_TAGS", Value: ""}, + {Name: "APP_PYROSCOPE_INCLUDE_POD_TAGS", Value: "true"}, {Name: "ROUTER_CONFIG_FILE", Value: "/app/config/fiber.yml"}, {Name: "ROUTER_PROTOCOL", Value: string(routerConfig.HTTP)}, {Name: "APP_SENTRY_ENABLED", Value: "true"}, {Name: "APP_SENTRY_DSN", Value: "sentry-dsn"}, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + { + Name: "POD_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + }, + }, {Name: "APP_LOGLEVEL", Value: "INFO"}, {Name: "APP_CUSTOM_METRICS", Value: "false"}, {Name: "APP_JAEGER_ENABLED", Value: "false"}, + {Name: "APP_OTEL_ENABLED", Value: "false"}, + {Name: "APP_PYROSCOPE_ENABLED", Value: "false"}, {Name: "APP_RESULT_LOGGER", Value: "bigquery"}, {Name: "APP_FIBER_DEBUG_LOG", Value: "false"}, {Name: "APP_GCP_PROJECT", Value: "gcp-project-id"}, @@ -640,13 +740,33 @@ func TestNewRouterService(t *testing.T) { {Name: "APP_ENVIRONMENT", Value: "test-env"}, {Name: "ROUTER_TIMEOUT", Value: "5s"}, {Name: "APP_JAEGER_COLLECTOR_ENDPOINT", Value: "jaeger-endpoint"}, + {Name: "APP_OTEL_COLLECTOR_ENDPOINT", Value: "otel-endpoint"}, + {Name: "APP_OTEL_SAMPLING_RATIO", Value: "0"}, + {Name: "APP_PYROSCOPE_SERVER_ADDRESS", Value: "pyroscope-address"}, + {Name: "APP_PYROSCOPE_HTTP_HEADERS", Value: ""}, + {Name: "APP_PYROSCOPE_CUSTOM_TAGS", Value: ""}, + {Name: "APP_PYROSCOPE_INCLUDE_POD_TAGS", Value: "true"}, {Name: "ROUTER_CONFIG_FILE", Value: "/app/config/fiber.yml"}, {Name: "ROUTER_PROTOCOL", Value: string(routerConfig.HTTP)}, {Name: "APP_SENTRY_ENABLED", Value: "true"}, {Name: "APP_SENTRY_DSN", Value: "sentry-dsn"}, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + { + Name: "POD_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + }, + }, {Name: "APP_LOGLEVEL", Value: "INFO"}, {Name: "APP_CUSTOM_METRICS", Value: "false"}, {Name: "APP_JAEGER_ENABLED", Value: "false"}, + {Name: "APP_OTEL_ENABLED", Value: "false"}, + {Name: "APP_PYROSCOPE_ENABLED", Value: "false"}, {Name: "APP_RESULT_LOGGER", Value: "bigquery"}, {Name: "APP_FIBER_DEBUG_LOG", Value: "false"}, {Name: "APP_GCP_PROJECT", Value: "gcp-project-id"}, @@ -741,13 +861,33 @@ func TestNewRouterService(t *testing.T) { {Name: "APP_ENVIRONMENT", Value: "test-env"}, {Name: "ROUTER_TIMEOUT", Value: "5s"}, {Name: "APP_JAEGER_COLLECTOR_ENDPOINT", Value: "jaeger-endpoint"}, + {Name: "APP_OTEL_COLLECTOR_ENDPOINT", Value: "otel-endpoint"}, + {Name: "APP_OTEL_SAMPLING_RATIO", Value: "0"}, + {Name: "APP_PYROSCOPE_SERVER_ADDRESS", Value: "pyroscope-address"}, + {Name: "APP_PYROSCOPE_HTTP_HEADERS", Value: ""}, + {Name: "APP_PYROSCOPE_CUSTOM_TAGS", Value: ""}, + {Name: "APP_PYROSCOPE_INCLUDE_POD_TAGS", Value: "true"}, {Name: "ROUTER_CONFIG_FILE", Value: "/app/config/fiber.yml"}, {Name: "ROUTER_PROTOCOL", Value: string(routerConfig.HTTP)}, {Name: "APP_SENTRY_ENABLED", Value: "true"}, {Name: "APP_SENTRY_DSN", Value: "sentry-dsn"}, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + { + Name: "POD_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + }, + }, {Name: "APP_LOGLEVEL", Value: "INFO"}, {Name: "APP_CUSTOM_METRICS", Value: "false"}, {Name: "APP_JAEGER_ENABLED", Value: "false"}, + {Name: "APP_OTEL_ENABLED", Value: "false"}, + {Name: "APP_PYROSCOPE_ENABLED", Value: "false"}, {Name: "APP_RESULT_LOGGER", Value: "bigquery"}, {Name: "APP_FIBER_DEBUG_LOG", Value: "false"}, {Name: "APP_GCP_PROJECT", Value: "gcp-project-id"}, @@ -842,15 +982,35 @@ func TestNewRouterService(t *testing.T) { {Name: "APP_ENVIRONMENT", Value: "test-env"}, {Name: "ROUTER_TIMEOUT", Value: "5s"}, {Name: "APP_JAEGER_COLLECTOR_ENDPOINT", Value: "jaeger-endpoint"}, + {Name: "APP_OTEL_COLLECTOR_ENDPOINT", Value: "otel-endpoint"}, + {Name: "APP_OTEL_SAMPLING_RATIO", Value: "0"}, + {Name: "APP_PYROSCOPE_SERVER_ADDRESS", Value: "pyroscope-address"}, + {Name: "APP_PYROSCOPE_HTTP_HEADERS", Value: ""}, + {Name: "APP_PYROSCOPE_CUSTOM_TAGS", Value: ""}, + {Name: "APP_PYROSCOPE_INCLUDE_POD_TAGS", Value: "true"}, {Name: "ROUTER_CONFIG_FILE", Value: "/app/config/fiber.yml"}, {Name: "ROUTER_PROTOCOL", Value: string(routerConfig.HTTP)}, {Name: "APP_SENTRY_ENABLED", Value: "true"}, {Name: "APP_SENTRY_DSN", Value: "sentry-dsn"}, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + { + Name: "POD_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + }, + }, {Name: "GOOGLE_APPLICATION_CREDENTIALS_EXPERIMENT_ENGINE", Value: "/var/secret/exp-engine/exp-engine-service-account.json"}, {Name: "APP_LOGLEVEL", Value: "INFO"}, {Name: "APP_CUSTOM_METRICS", Value: "false"}, {Name: "APP_JAEGER_ENABLED", Value: "false"}, + {Name: "APP_OTEL_ENABLED", Value: "false"}, + {Name: "APP_PYROSCOPE_ENABLED", Value: "false"}, {Name: "APP_RESULT_LOGGER", Value: "nop"}, {Name: "APP_FIBER_DEBUG_LOG", Value: "false"}, }, @@ -972,13 +1132,33 @@ func TestNewRouterService(t *testing.T) { {Name: "APP_ENVIRONMENT", Value: "test-env"}, {Name: "ROUTER_TIMEOUT", Value: "5s"}, {Name: "APP_JAEGER_COLLECTOR_ENDPOINT", Value: "jaeger-endpoint"}, + {Name: "APP_OTEL_COLLECTOR_ENDPOINT", Value: "otel-endpoint"}, + {Name: "APP_OTEL_SAMPLING_RATIO", Value: "0"}, + {Name: "APP_PYROSCOPE_SERVER_ADDRESS", Value: "pyroscope-address"}, + {Name: "APP_PYROSCOPE_HTTP_HEADERS", Value: ""}, + {Name: "APP_PYROSCOPE_CUSTOM_TAGS", Value: ""}, + {Name: "APP_PYROSCOPE_INCLUDE_POD_TAGS", Value: "true"}, {Name: "ROUTER_CONFIG_FILE", Value: "/app/config/fiber.yml"}, {Name: "ROUTER_PROTOCOL", Value: string(routerConfig.HTTP)}, {Name: "APP_SENTRY_ENABLED", Value: "true"}, {Name: "APP_SENTRY_DSN", Value: "sentry-dsn"}, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + { + Name: "POD_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + }, + }, {Name: "APP_LOGLEVEL", Value: "INFO"}, {Name: "APP_CUSTOM_METRICS", Value: "false"}, {Name: "APP_JAEGER_ENABLED", Value: "false"}, + {Name: "APP_OTEL_ENABLED", Value: "false"}, + {Name: "APP_PYROSCOPE_ENABLED", Value: "false"}, {Name: "APP_RESULT_LOGGER", Value: "nop"}, {Name: "APP_FIBER_DEBUG_LOG", Value: "false"}, }, @@ -1048,6 +1228,9 @@ func TestNewRouterService(t *testing.T) { data.expRawConfig, &config.RouterDefaults{ JaegerCollectorEndpoint: "jaeger-endpoint", + OtelCollectorEndpoint: "otel-endpoint", + PyroscopeServerAddress: "pyroscope-address", + PyroscopeIncludePodTags: true, FluentdConfig: &config.FluentdConfig{Tag: "fluentd-tag"}, }, true, @@ -1138,6 +1321,9 @@ func TestBuildRouterEnvsResultLogger(t *testing.T) { environmentType: "dev", routerDefaults: &config.RouterDefaults{ JaegerCollectorEndpoint: "", + OtelCollectorEndpoint: "http://otel-collector.example.com:4318", + PyroscopeServerAddress: "http://pyroscope.example.com:4040", + PyroscopeCustomTags: map[string]string{"team": "fraud"}, FluentdConfig: &config.FluentdConfig{Tag: ""}, KafkaConfig: &config.KafkaConfig{ MaxMessageBytes: 123, @@ -1171,13 +1357,33 @@ func TestBuildRouterEnvsResultLogger(t *testing.T) { {Name: "APP_ENVIRONMENT", Value: "dev"}, {Name: "ROUTER_TIMEOUT", Value: "10s"}, {Name: "APP_JAEGER_COLLECTOR_ENDPOINT", Value: ""}, + {Name: "APP_OTEL_COLLECTOR_ENDPOINT", Value: "http://otel-collector.example.com:4318"}, + {Name: "APP_OTEL_SAMPLING_RATIO", Value: "0"}, + {Name: "APP_PYROSCOPE_SERVER_ADDRESS", Value: "http://pyroscope.example.com:4040"}, + {Name: "APP_PYROSCOPE_HTTP_HEADERS", Value: ""}, + {Name: "APP_PYROSCOPE_CUSTOM_TAGS", Value: "team:fraud"}, + {Name: "APP_PYROSCOPE_INCLUDE_POD_TAGS", Value: "false"}, {Name: "ROUTER_CONFIG_FILE", Value: "/app/config/fiber.yml"}, {Name: "ROUTER_PROTOCOL", Value: string(routerConfig.HTTP)}, {Name: "APP_SENTRY_ENABLED", Value: "false"}, {Name: "APP_SENTRY_DSN", Value: ""}, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + { + Name: "POD_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + }, + }, {Name: "APP_LOGLEVEL", Value: "DEBUG"}, {Name: "APP_CUSTOM_METRICS", Value: "false"}, {Name: "APP_JAEGER_ENABLED", Value: "false"}, + {Name: "APP_OTEL_ENABLED", Value: "false"}, + {Name: "APP_PYROSCOPE_ENABLED", Value: "false"}, {Name: "APP_RESULT_LOGGER", Value: "kafka"}, {Name: "APP_FIBER_DEBUG_LOG", Value: "false"}, {Name: "APP_KAFKA_BROKERS", Value: "1.1.1.1:1111"}, @@ -1216,13 +1422,33 @@ func TestBuildRouterEnvsResultLogger(t *testing.T) { {Name: "APP_ENVIRONMENT", Value: ""}, {Name: "ROUTER_TIMEOUT", Value: ""}, {Name: "APP_JAEGER_COLLECTOR_ENDPOINT", Value: ""}, + {Name: "APP_OTEL_COLLECTOR_ENDPOINT", Value: ""}, + {Name: "APP_OTEL_SAMPLING_RATIO", Value: "0"}, + {Name: "APP_PYROSCOPE_SERVER_ADDRESS", Value: ""}, + {Name: "APP_PYROSCOPE_HTTP_HEADERS", Value: ""}, + {Name: "APP_PYROSCOPE_CUSTOM_TAGS", Value: ""}, + {Name: "APP_PYROSCOPE_INCLUDE_POD_TAGS", Value: "false"}, {Name: "ROUTER_CONFIG_FILE", Value: "/app/config/fiber.yml"}, {Name: "ROUTER_PROTOCOL", Value: string(routerConfig.UPI)}, {Name: "APP_SENTRY_ENABLED", Value: "false"}, {Name: "APP_SENTRY_DSN", Value: ""}, + { + Name: "POD_NAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.name"}, + }, + }, + { + Name: "POD_NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{FieldPath: "metadata.namespace"}, + }, + }, {Name: "APP_LOGLEVEL", Value: ""}, {Name: "APP_CUSTOM_METRICS", Value: "false"}, {Name: "APP_JAEGER_ENABLED", Value: "false"}, + {Name: "APP_OTEL_ENABLED", Value: "false"}, + {Name: "APP_PYROSCOPE_ENABLED", Value: "false"}, {Name: "APP_RESULT_LOGGER", Value: "upi"}, {Name: "APP_FIBER_DEBUG_LOG", Value: "false"}, {Name: "APP_KAFKA_BROKERS", Value: "broker"}, @@ -1250,3 +1476,45 @@ func TestBuildRouterEnvsResultLogger(t *testing.T) { }) } } + +func TestFormatMapEnvVar(t *testing.T) { + tests := []struct { + name string + m map[string]string + want string + }{ + { + name: "nil", + m: nil, + want: "", + }, + { + name: "empty", + m: map[string]string{}, + want: "", + }, + { + name: "single entry", + m: map[string]string{"Authorization": "Bearer token"}, + want: "Authorization:Bearer token", + }, + { + name: "multiple entries sorted by key regardless of map order", + m: map[string]string{ + "X-Scope-OrgID": "tenant1", + "Authorization": "Bearer token", + "X-Custom": "value", + }, + want: "Authorization:Bearer token,X-Custom:value,X-Scope-OrgID:tenant1", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // Run repeatedly since Go map iteration order is randomized per run, + // to catch any accidental reliance on iteration order. + for i := 0; i < 5; i++ { + assert.Equal(t, tt.want, formatMapEnvVar(tt.m)) + } + }) + } +} diff --git a/api/turing/config/config.go b/api/turing/config/config.go index d7a84a1f3..fe8c6670e 100644 --- a/api/turing/config/config.go +++ b/api/turing/config/config.go @@ -83,6 +83,8 @@ type Config struct { KnativeServiceDefaults *KnativeServiceDefaults NewRelicConfig newrelic.Config Sentry sentry.Config + Otel OtelConfig + Pyroscope PyroscopeConfig ClusterConfig ClusterConfig `validate:"required"` TuringEncryptionKey string `validate:"required"` AlertConfig *AlertConfig @@ -324,10 +326,41 @@ type RouterDefaults struct { // Enable router custom metrics CustomMetricsEnabled bool // Enable Jaeger Tracing + // + // Deprecated: Jaeger's native Thrift ingestion is being phased out; use + // OtelEnabled instead unless a specific downstream backend still requires + // Thrift. This field will be removed in a future release. JaegerEnabled bool - // Jaeger collector endpoint. If JaegerEnabled is true, this value - // must be set. + // Jaeger collector endpoint (Thrift-over-HTTP). If JaegerEnabled is true, this + // value must be set. + // + // Deprecated: use OtelCollectorEndpoint instead. JaegerCollectorEndpoint string + // Enable router tracing via OpenTelemetry, exported over OTLP HTTP + OtelEnabled bool + // OTLP HTTP endpoint routers should export traces to. If OtelEnabled is true, + // this value must be set. + OtelCollectorEndpoint string `validate:"required_if=OtelEnabled True"` + // OtelSamplingRatio is the fraction of traces routers should sample, between 0 and 1. + // Defaults to 0.01. + OtelSamplingRatio float64 + // Enable Pyroscope profiling for routers deployed by this instance of the Turing API + PyroscopeEnabled bool + // Pyroscope server address routers should report profiles to. If PyroscopeEnabled is + // true, this value must be set. + PyroscopeServerAddress string `validate:"required_if=PyroscopeEnabled True"` + // HTTP headers routers should attach to every profile push request they make to + // PyroscopeServerAddress, e.g. for auth (Authorization, X-Scope-OrgID, ...). Optional. + PyroscopeHTTPHeaders map[string]string + // PyroscopeCustomTags are additional static tags routers should attach to every profile, + // on top of the built-in router_name/pod_name/pod_namespace tags. If a key collides with + // one of those, the built-in value wins. Optional. + PyroscopeCustomTags map[string]string + // PyroscopeIncludePodTags controls whether routers tag their Pyroscope profiles with + // pod_name/pod_namespace (from the POD_NAME/POD_NAMESPACE downward API env vars), in + // addition to the always-present router_name tag. Defaults to true; set to false to opt + // out deployment-wide, e.g. if per-pod cardinality is undesirable in Pyroscope. + PyroscopeIncludePodTags bool // Router log level LogLevel string `validate:"required"` // Fluentd config for the router @@ -349,6 +382,33 @@ type RouterDefaults struct { UPIConfig *UPIConfig } +// OtelConfig captures the settings for HTTP-layer request tracing using OpenTelemetry +type OtelConfig struct { + Enabled bool + // OtlpEndpoint is the OTLP HTTP endpoint spans are exported to, e.g. http://otel-collector:4318. + // If Enabled is true, this value must be set. + OtlpEndpoint string `validate:"required_if=Enabled True"` + // SamplingRatio is the fraction of traces to sample, between 0 and 1. Defaults to 0.01. + SamplingRatio float64 +} + +// PyroscopeConfig captures the settings for continuous profiling of the Turing API using Pyroscope +type PyroscopeConfig struct { + Enabled bool + // ServerAddress is the Pyroscope server address to report profiles to. If Enabled is + // true, this value must be set. + ServerAddress string `validate:"required_if=Enabled True"` + // HTTPHeaders are attached to every profile push request, e.g. for auth + // (Authorization, X-Scope-OrgID, ...). Optional. + HTTPHeaders map[string]string + // CustomTags are additional static tags attached to every profile. Optional. + CustomTags map[string]string + // IncludePodTags controls whether profiles are additionally tagged with pod_name/ + // pod_namespace (from the POD_NAME/POD_NAMESPACE downward API env vars), to distinguish + // individual replicas of the Turing API deployment. Defaults to true. + IncludePodTags bool +} + // FluentdConfig captures the defaults used by the Turing Router when Fluentd is enabled type FluentdConfig struct { // Image to use for fluentd deployments, in the format registry/repository:version. @@ -610,6 +670,13 @@ func setDefaultValues(v *viper.Viper) { v.SetDefault("RouterDefaults::CustomMetricsEnabled", "false") v.SetDefault("RouterDefaults::JaegerEnabled", "false") v.SetDefault("RouterDefaults::JaegerCollectorEndpoint", "") + v.SetDefault("RouterDefaults::OtelEnabled", "false") + v.SetDefault("RouterDefaults::OtelCollectorEndpoint", "") + v.SetDefault("RouterDefaults::OtelSamplingRatio", "0.01") + v.SetDefault("RouterDefaults::PyroscopeEnabled", "false") + v.SetDefault("RouterDefaults::PyroscopeServerAddress", "") + v.SetDefault("RouterDefaults::PyroscopeCustomTags", map[string]interface{}{}) + v.SetDefault("RouterDefaults::PyroscopeIncludePodTags", "true") v.SetDefault("RouterDefaults::LogLevel", "INFO") v.SetDefault("RouterDefaults::FluentdConfig::Image", "") v.SetDefault("RouterDefaults::FluentdConfig::Tag", "turing-result.log") @@ -622,6 +689,14 @@ func setDefaultValues(v *viper.Viper) { v.SetDefault("Sentry::Enabled", "false") v.SetDefault("Sentry::DSN", "") + v.SetDefault("Otel::Enabled", "false") + v.SetDefault("Otel::OtlpEndpoint", "") + v.SetDefault("Otel::SamplingRatio", "0.01") + + v.SetDefault("Pyroscope::Enabled", "false") + v.SetDefault("Pyroscope::ServerAddress", "") + v.SetDefault("Pyroscope::IncludePodTags", "true") + v.SetDefault("TuringEncryptionKey", "") v.SetDefault("AlertConfig::Enabled", "false") diff --git a/api/turing/config/config_test.go b/api/turing/config/config_test.go index 114ced468..7e69e734a 100644 --- a/api/turing/config/config_test.go +++ b/api/turing/config/config_test.go @@ -175,7 +175,8 @@ func TestLoad(t *testing.T) { UserContainerMemoryLimitRequestFactor: 1, }, RouterDefaults: &config.RouterDefaults{ - LogLevel: "INFO", + LogLevel: "INFO", + OtelSamplingRatio: 0.01, FluentdConfig: &config.FluentdConfig{ Tag: "turing-result.log", FlushIntervalSeconds: 90, @@ -185,8 +186,11 @@ func TestLoad(t *testing.T) { MaxMessageBytes: 1048588, CompressionType: "none", }, + PyroscopeIncludePodTags: true, }, - Sentry: sentry.Config{}, + Otel: config.OtelConfig{SamplingRatio: 0.01}, + Pyroscope: config.PyroscopeConfig{IncludePodTags: true}, + Sentry: sentry.Config{}, ClusterConfig: config.ClusterConfig{ InClusterConfig: false, }, @@ -291,7 +295,8 @@ func TestLoad(t *testing.T) { }, }, RouterDefaults: &config.RouterDefaults{ - LogLevel: "INFO", + LogLevel: "INFO", + OtelSamplingRatio: 0.01, FluentdConfig: &config.FluentdConfig{ Tag: "turing-result.log", FlushIntervalSeconds: 60, @@ -301,7 +306,18 @@ func TestLoad(t *testing.T) { MaxMessageBytes: 1048588, CompressionType: "none", }, + PyroscopeEnabled: true, + PyroscopeServerAddress: "http://pyroscope.example.com:4040", + // viper lowercases YAML map keys, so header names configured this way + // always come out lowercase (harmless: HTTP header names are + // case-insensitive). + PyroscopeHTTPHeaders: map[string]string{"authorization": "Bearer token"}, + PyroscopeIncludePodTags: true, + OtelEnabled: true, + OtelCollectorEndpoint: "http://otel-collector.example.com:4318", }, + Otel: config.OtelConfig{SamplingRatio: 0.01}, + Pyroscope: config.PyroscopeConfig{IncludePodTags: true}, Sentry: sentry.Config{ Enabled: true, Labels: map[string]string{"foo": "bar"}, @@ -439,7 +455,8 @@ func TestLoad(t *testing.T) { }, }, RouterDefaults: &config.RouterDefaults{ - LogLevel: "INFO", + LogLevel: "INFO", + OtelSamplingRatio: 0.01, FluentdConfig: &config.FluentdConfig{ Tag: "turing-result.log", FlushIntervalSeconds: 90, @@ -464,7 +481,18 @@ func TestLoad(t *testing.T) { MaxMessageBytes: 1234567, CompressionType: "snappy", }, + PyroscopeEnabled: true, + PyroscopeServerAddress: "http://pyroscope.example.com:4040", + // viper lowercases YAML map keys, so header names configured this way + // always come out lowercase (harmless: HTTP header names are + // case-insensitive). + PyroscopeHTTPHeaders: map[string]string{"authorization": "Bearer token"}, + PyroscopeIncludePodTags: true, + OtelEnabled: true, + OtelCollectorEndpoint: "http://otel-collector.example.com:4318", }, + Otel: config.OtelConfig{SamplingRatio: 0.01}, + Pyroscope: config.PyroscopeConfig{IncludePodTags: true}, Sentry: sentry.Config{ Enabled: true, Labels: map[string]string{"foo": "bar"}, @@ -620,7 +648,8 @@ func TestLoad(t *testing.T) { }, }, RouterDefaults: &config.RouterDefaults{ - LogLevel: "INFO", + LogLevel: "INFO", + OtelSamplingRatio: 0.01, FluentdConfig: &config.FluentdConfig{ Tag: "turing-result.log", FlushIntervalSeconds: 90, @@ -645,7 +674,18 @@ func TestLoad(t *testing.T) { MaxMessageBytes: 1234567, CompressionType: "snappy", }, + PyroscopeEnabled: true, + PyroscopeServerAddress: "http://pyroscope.example.com:4040", + // viper lowercases YAML map keys, so header names configured this way + // always come out lowercase (harmless: HTTP header names are + // case-insensitive). + PyroscopeHTTPHeaders: map[string]string{"authorization": "Bearer token"}, + PyroscopeIncludePodTags: true, + OtelEnabled: true, + OtelCollectorEndpoint: "http://otel-collector.example.com:4318", }, + Otel: config.OtelConfig{SamplingRatio: 0.01}, + Pyroscope: config.PyroscopeConfig{IncludePodTags: true}, Sentry: sentry.Config{ Enabled: true, Labels: map[string]string{"foo": "bar"}, @@ -740,6 +780,21 @@ func TestLoad(t *testing.T) { } } +func TestLoad_OtelAndPyroscope(t *testing.T) { + cfg, err := config.Load("testdata/config-1.yaml") + require.NoError(t, err) + + assert.Equal(t, false, cfg.Otel.Enabled) + assert.Equal(t, float64(0.01), cfg.Otel.SamplingRatio) + assert.Equal(t, false, cfg.Pyroscope.Enabled) + assert.Equal(t, true, cfg.RouterDefaults.PyroscopeEnabled) + assert.Equal(t, "http://pyroscope.example.com:4040", cfg.RouterDefaults.PyroscopeServerAddress) + assert.Equal(t, map[string]string{"authorization": "Bearer token"}, cfg.RouterDefaults.PyroscopeHTTPHeaders) + assert.Equal(t, true, cfg.RouterDefaults.PyroscopeIncludePodTags) + assert.Equal(t, true, cfg.RouterDefaults.OtelEnabled) + assert.Equal(t, "http://otel-collector.example.com:4318", cfg.RouterDefaults.OtelCollectorEndpoint) +} + // Reference: // https://github.com/mitchellh/mapstructure/blob/ce2ff0c13ce509e36e9254c08ea0bca90ed5af6c/decode_hooks_test.go#L128 func TestStringToQuantityHookFunc(t *testing.T) { @@ -1058,6 +1113,43 @@ func TestConfigValidate(t *testing.T) { }, wantErr: true, }, + "otel enabled but missing OtlpEndpoint": { + validConfigUpdate: func(validConfig config.Config) config.Config { + validConfig.Otel = config.OtelConfig{Enabled: true} + return validConfig + }, + wantErr: true, + }, + "otel enabled with OtlpEndpoint set": { + validConfigUpdate: func(validConfig config.Config) config.Config { + validConfig.Otel = config.OtelConfig{Enabled: true, OtlpEndpoint: "http://otel-collector.example.com:4318"} + return validConfig + }, + wantErr: false, + }, + "api pyroscope enabled but missing ServerAddress": { + validConfigUpdate: func(validConfig config.Config) config.Config { + validConfig.Pyroscope = config.PyroscopeConfig{Enabled: true} + return validConfig + }, + wantErr: true, + }, + "router defaults pyroscope enabled but missing PyroscopeServerAddress": { + validConfigUpdate: func(validConfig config.Config) config.Config { + validConfig.RouterDefaults.PyroscopeEnabled = true + validConfig.RouterDefaults.PyroscopeServerAddress = "" + return validConfig + }, + wantErr: true, + }, + "router defaults otel enabled but missing OtelCollectorEndpoint": { + validConfigUpdate: func(validConfig config.Config) config.Config { + validConfig.RouterDefaults.OtelEnabled = true + validConfig.RouterDefaults.OtelCollectorEndpoint = "" + return validConfig + }, + wantErr: true, + }, } for name, tt := range tests { t.Run(name, func(t *testing.T) { diff --git a/api/turing/config/example.yaml b/api/turing/config/example.yaml index c6a94e3df..8504ac48c 100644 --- a/api/turing/config/example.yaml +++ b/api/turing/config/example.yaml @@ -148,8 +148,32 @@ RouterDefaults: Image: ghcr.io/caraml-dev/turing:latest FiberDebugLogEnabled: false CustomMetricsEnabled: false + # Deprecated: Jaeger's native Thrift ingestion is being phased out; use + # OtelEnabled/OtelCollectorEndpoint instead unless a specific downstream + # backend still requires Thrift. JaegerEnabled: false - JaegerCollectorEndpoint: http://jaeger-tracing-collector.example.com:14268/api/traces + JaegerCollectorEndpoint: http://jaeger-collector.example.com:14268/api/traces + OtelEnabled: false + OtelCollectorEndpoint: http://otel-collector.example.com:4318 + # Fraction of traces routers should sample, between 0 and 1. Defaults to 0.01. + OtelSamplingRatio: 0.01 + PyroscopeEnabled: false + PyroscopeServerAddress: http://pyroscope.example.com:4040 + # HTTP headers attached to every profile push request routers make to + # PyroscopeServerAddress, e.g. for auth. Optional, omit entirely if the server + # doesn't require auth. Note: header names are lowercased by the config + # loader; this is harmless since HTTP header names are case-insensitive. + PyroscopeHTTPHeaders: + Authorization: " or "Bearer "> + # Additional static tags attached to every profile, on top of the built-in + # router_name/pod_name/pod_namespace tags. If a key collides with one of those, the + # built-in value wins. Optional, omit entirely if not needed. + PyroscopeCustomTags: + team: fraud + # Tag Pyroscope profiles with pod_name/pod_namespace (in addition to the always-present + # router_name tag), so individual pods of a multi-replica router deployment can be told + # apart. Defaults to true; set to false to opt out deployment-wide. + PyroscopeIncludePodTags: true LogLevel: INFO # Fluentd log forwarder configuration that can be used in Turing router @@ -171,6 +195,31 @@ RouterDefaults: # Note that {{.ProjectName}}, {{.ClusterName}}, {{.RouterName}} and {{.Version}} is required MonitoringURLFormat: "https://www.example.com/{{.ClusterName}}/{{.ProjectName}}/{{.RouterName}}/{{.Version}}" +# OpenTelemetry (OTEL) tracing configuration +Otel: + Enabled: false + OtlpEndpoint: http://otel-collector.example.com:4318 + SamplingRatio: 0.01 + +# Pyroscope profiling service configuration +Pyroscope: + Enabled: false + ServerAddress: http://pyroscope.example.com:4040 + # HTTP headers attached to every profile push request, e.g. for auth. Optional, + # omit entirely if the server doesn't require auth. Note: header names are + # lowercased by the config loader; this is harmless since HTTP header names + # are case-insensitive. + HTTPHeaders: + Authorization: " or "Bearer "> + # Additional static tags attached to every profile. Optional, omit entirely if not needed. + CustomTags: + team: fraud + # Tag Pyroscope profiles with pod_name/pod_namespace, so individual replicas of the + # Turing API deployment can be told apart. Requires the POD_NAME/POD_NAMESPACE env vars + # to be populated, e.g. via the Kubernetes downward API (turing.extraEnvs in the Helm + # chart). Defaults to true; set to false to opt out. + IncludePodTags: true + # Sentry application monitoring service configuration # https://docs.sentry.io/product/sentry-basics/dsn-explainer/ Sentry: diff --git a/api/turing/config/testdata/config-1.yaml b/api/turing/config/testdata/config-1.yaml index 968217574..fe9617ef8 100644 --- a/api/turing/config/testdata/config-1.yaml +++ b/api/turing/config/testdata/config-1.yaml @@ -55,6 +55,12 @@ RouterDefaults: FluentdConfig: FlushIntervalSeconds: 60 WorkerCount: 2 + PyroscopeEnabled: true + PyroscopeServerAddress: http://pyroscope.example.com:4040 + PyroscopeHTTPHeaders: + Authorization: Bearer token + OtelEnabled: true + OtelCollectorEndpoint: http://otel-collector.example.com:4318 Sentry: Enabled: true Labels: diff --git a/api/turing/internal/testutils/validation.go b/api/turing/internal/testutils/validation.go index a3ed80f0c..b7105a2b3 100644 --- a/api/turing/internal/testutils/validation.go +++ b/api/turing/internal/testutils/validation.go @@ -11,11 +11,11 @@ import ( // If the object types have unexported fields, a custom marshaler is required to be defined. func CompareObjects(actual interface{}, expected interface{}) error { allowUnexportedOn := actual - if reflect.TypeOf(allowUnexportedOn).Kind() == reflect.Ptr { + if reflect.TypeOf(allowUnexportedOn).Kind() == reflect.Pointer { allowUnexportedOn = reflect.ValueOf(actual).Elem().Interface() } if !cmp.Equal(actual, expected, cmp.AllowUnexported(allowUnexportedOn)) { - return fmt.Errorf(cmp.Diff(actual, expected, cmp.AllowUnexported(allowUnexportedOn))) + return fmt.Errorf("%s", cmp.Diff(actual, expected, cmp.AllowUnexported(allowUnexportedOn))) } return nil } diff --git a/api/turing/models/log_config.go b/api/turing/models/log_config.go index 2114aca8c..81fc44e66 100644 --- a/api/turing/models/log_config.go +++ b/api/turing/models/log_config.go @@ -64,7 +64,13 @@ type LogConfig struct { // Enable debug logs for Fiber. Defaults to false. FiberDebugLogEnabled bool `json:"fiber_debug_log_enabled"` // Enable Jaeger tracing. + // + // Deprecated: use OtelEnabled instead. Will be removed in a future release. JaegerEnabled bool `json:"jaeger_enabled"` + // Enable OpenTelemetry tracing. + OtelEnabled bool `json:"otel_enabled"` + // Enable Pyroscope profiling. + PyroscopeEnabled bool `json:"pyroscope_enabled"` // Result Logger type. The associated config must not be null. ResultLoggerType ResultLogger `json:"result_logger_type"` // Configuration necessary to log results to BigQuery. Cannot be empty if diff --git a/api/turing/models/log_config_test.go b/api/turing/models/log_config_test.go index 679464512..1a52251f2 100644 --- a/api/turing/models/log_config_test.go +++ b/api/turing/models/log_config_test.go @@ -26,6 +26,8 @@ func TestLogConfigValue(t *testing.T) { "custom_metrics_enabled": true, "fiber_debug_log_enabled": false, "jaeger_enabled": false, + "otel_enabled": false, + "pyroscope_enabled": false, "result_logger_type": "nop" }`), }, @@ -44,6 +46,8 @@ func TestLogConfigValue(t *testing.T) { "custom_metrics_enabled": false, "fiber_debug_log_enabled": false, "jaeger_enabled": false, + "otel_enabled": false, + "pyroscope_enabled": false, "result_logger_type": "bigquery", "bigquery_config": { "table": "test-table", @@ -67,6 +71,8 @@ func TestLogConfigValue(t *testing.T) { "custom_metrics_enabled": false, "fiber_debug_log_enabled": false, "jaeger_enabled": false, + "otel_enabled": false, + "pyroscope_enabled": false, "result_logger_type": "kafka", "kafka_config": { "brokers": "test-brokers", diff --git a/api/turing/server/api.go b/api/turing/server/api.go index fac1ef398..80c23e96c 100644 --- a/api/turing/server/api.go +++ b/api/turing/server/api.go @@ -8,6 +8,7 @@ import ( "github.com/gorilla/mux" "github.com/pkg/errors" "github.com/rs/cors" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "github.com/caraml-dev/turing/api/turing/api" "github.com/caraml-dev/turing/api/turing/config" @@ -59,7 +60,9 @@ func AddAPIRoutesHandler(r *mux.Router, path string, appCtx *api.AppContext, cfg for _, c := range controllers { for _, route := range c.Routes() { // NewRelic handler - _, handler := newrelic.WrapHandle(route.Name(), route.HandlerFunc(validator)) + _, nrHandler := newrelic.WrapHandle(route.Name(), route.HandlerFunc(validator)) + // Wrap with OTel span, alongside (not replacing) the New Relic instrumentation above + handler := otelhttp.NewHandler(nrHandler, route.Name()) apiRouter.Name(route.Name()). Methods(route.Method()). diff --git a/api/turing/server/application.go b/api/turing/server/application.go index 410b51d89..0930e7896 100644 --- a/api/turing/server/application.go +++ b/api/turing/server/application.go @@ -1,6 +1,7 @@ package server import ( + "context" "flag" "net/http" "strings" @@ -74,6 +75,30 @@ func Run() { } defer newrelic.Shutdown(5 * time.Second) + // Initialise OTel tracer + tracerShutdown, err := initTracer(cfg.Otel) + if err != nil { + log.Errorf("Failed to initialize OTel tracer: %s", err) + } + defer func() { + if err := tracerShutdown(context.Background()); err != nil { + log.Errorf("Failed to shut down OTel tracer: %s", err) + } + }() + + // Initialise Pyroscope profiler + profiler, err := initProfiler(cfg.Pyroscope) + if err != nil { + log.Errorf("Failed to initialize Pyroscope profiler: %s", err) + } + if profiler != nil { + defer func() { + if err := profiler.Stop(); err != nil { + log.Errorf("Failed to stop Pyroscope profiler: %s", err) + } + }() + } + // Init app context appCtx, err := api.NewAppContext(db, cfg) if err != nil { diff --git a/api/turing/server/instrumentation.go b/api/turing/server/instrumentation.go new file mode 100644 index 000000000..53f7e32f3 --- /dev/null +++ b/api/turing/server/instrumentation.go @@ -0,0 +1,115 @@ +package server + +import ( + "context" + "fmt" + "os" + + "github.com/grafana/pyroscope-go" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + + "github.com/caraml-dev/turing/api/turing/config" +) + +const appName = "turing-api" + +// envPodName and envPodNamespace are expected to be populated via the Kubernetes downward +// API, e.g. through turing.extraEnvs in the Helm chart. They are absent when running +// outside a pod (e.g. local dev) or when not configured. +const ( + envPodName = "POD_NAME" + envPodNamespace = "POD_NAMESPACE" +) + +// initTracer initializes the global OpenTelemetry tracer provider for api, exporting +// spans via OTLP HTTP, and returns its shutdown function. When cfg.Enabled is false, +// it returns a no-op shutdown function and leaves the OTel globals untouched. The +// returned shutdown function is always non-nil and safe to call, even when a non-nil +// error is also returned, so callers can unconditionally defer it. +func initTracer(cfg config.OtelConfig) (func(context.Context) error, error) { + noopShutdown := func(context.Context) error { return nil } + + if !cfg.Enabled { + return noopShutdown, nil + } + + ctx := context.Background() + exporter, err := otlptracehttp.New(ctx, otlptracehttp.WithEndpointURL(cfg.OtlpEndpoint)) + if err != nil { + return noopShutdown, err + } + + ratio := cfg.SamplingRatio + if ratio <= 0 { + ratio = 1 + } + + res := resource.NewSchemaless(attribute.String("service.name", appName)) + + tp := sdktrace.NewTracerProvider( + sdktrace.WithBatcher(exporter), + sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(ratio))), + sdktrace.WithResource(res), + ) + + otel.SetTracerProvider(tp) + otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator( + propagation.TraceContext{}, propagation.Baggage{}, + )) + + return tp.Shutdown, nil +} + +// initProfiler starts continuous profiling via pyroscope-go if enabled in cfg. Returns +// a nil profiler and nil error when profiling is disabled. pyroscope.Start does not itself +// error on an empty ServerAddress -- it happily constructs a client that fails silently on +// every upload -- so an empty address is rejected explicitly here instead. +func initProfiler(cfg config.PyroscopeConfig) (*pyroscope.Profiler, error) { + if !cfg.Enabled { + return nil, nil + } + if cfg.ServerAddress == "" { + return nil, fmt.Errorf("pyroscope profiling is enabled but ServerAddress is empty") + } + + return pyroscope.Start(pyroscope.Config{ + ApplicationName: appName, + ServerAddress: cfg.ServerAddress, + HTTPHeaders: cfg.HTTPHeaders, + Tags: buildTags(cfg), + ProfileTypes: []pyroscope.ProfileType{ + pyroscope.ProfileCPU, + pyroscope.ProfileAllocObjects, + pyroscope.ProfileAllocSpace, + pyroscope.ProfileInuseObjects, + pyroscope.ProfileInuseSpace, + pyroscope.ProfileGoroutines, + }, + }) +} + +// buildTags returns the static Pyroscope tags for this process: cfg.CustomTags first, then +// pod_name/pod_namespace -- when cfg.IncludePodTags is true -- for whichever of the +// corresponding downward API env vars are set, to distinguish individual replicas of the +// Turing API deployment. pod_name/pod_namespace are applied last, so they always win over +// a colliding custom tag key. +func buildTags(cfg config.PyroscopeConfig) map[string]string { + tags := make(map[string]string, len(cfg.CustomTags)+2) + for k, v := range cfg.CustomTags { + tags[k] = v + } + if cfg.IncludePodTags { + if podName := os.Getenv(envPodName); podName != "" { + tags["pod_name"] = podName + } + if podNamespace := os.Getenv(envPodNamespace); podNamespace != "" { + tags["pod_namespace"] = podNamespace + } + } + return tags +} diff --git a/api/turing/server/instrumentation_test.go b/api/turing/server/instrumentation_test.go new file mode 100644 index 000000000..576f40891 --- /dev/null +++ b/api/turing/server/instrumentation_test.go @@ -0,0 +1,114 @@ +package server + +import ( + "context" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/caraml-dev/turing/api/turing/config" +) + +func TestInitTracer_Disabled(t *testing.T) { + shutdown, err := initTracer(config.OtelConfig{Enabled: false}) + require.NoError(t, err) + require.NotNil(t, shutdown) + assert.NoError(t, shutdown(context.Background())) +} + +func TestInitTracer_Enabled(t *testing.T) { + shutdown, err := initTracer(config.OtelConfig{ + Enabled: true, + OtlpEndpoint: "http://localhost:4318", + SamplingRatio: 0.5, + }) + require.NoError(t, err) + require.NotNil(t, shutdown) + assert.NoError(t, shutdown(context.Background())) +} + +func TestInitProfiler_Disabled(t *testing.T) { + profiler, err := initProfiler(config.PyroscopeConfig{Enabled: false}) + require.NoError(t, err) + assert.Nil(t, profiler) +} + +func TestInitProfiler_Enabled(t *testing.T) { + profiler, err := initProfiler(config.PyroscopeConfig{ + Enabled: true, + ServerAddress: "http://localhost:4040", + }) + require.NoError(t, err) + require.NotNil(t, profiler) + defer func() { _ = profiler.Stop() }() +} + +func TestInitProfiler_EnabledWithHTTPHeaders(t *testing.T) { + profiler, err := initProfiler(config.PyroscopeConfig{ + Enabled: true, + ServerAddress: "http://localhost:4040", + HTTPHeaders: map[string]string{"Authorization": "Bearer token"}, + }) + require.NoError(t, err) + require.NotNil(t, profiler) + defer func() { _ = profiler.Stop() }() +} + +func TestInitProfiler_EnabledWithCustomTags(t *testing.T) { + profiler, err := initProfiler(config.PyroscopeConfig{ + Enabled: true, + ServerAddress: "http://localhost:4040", + CustomTags: map[string]string{"team": "fraud"}, + }) + require.NoError(t, err) + require.NotNil(t, profiler) + defer func() { _ = profiler.Stop() }() +} + +func TestInitProfiler_EnabledEmptyServerAddress(t *testing.T) { + profiler, err := initProfiler(config.PyroscopeConfig{ + Enabled: true, + ServerAddress: "", + }) + require.Error(t, err) + assert.Nil(t, profiler) +} + +func TestBuildTags(t *testing.T) { + t.Run("empty when pod env vars are unset and no custom tags", func(t *testing.T) { + assert.Equal(t, map[string]string{}, buildTags(config.PyroscopeConfig{IncludePodTags: true})) + }) + + t.Run("includes pod_name and pod_namespace when set and IncludePodTags is true", func(t *testing.T) { + t.Setenv(envPodName, "turing-api-abc123") + t.Setenv(envPodNamespace, "test-namespace") + + assert.Equal(t, map[string]string{ + "pod_name": "turing-api-abc123", + "pod_namespace": "test-namespace", + }, buildTags(config.PyroscopeConfig{IncludePodTags: true})) + }) + + t.Run("omits pod_name and pod_namespace when IncludePodTags is false, even if set", func(t *testing.T) { + t.Setenv(envPodName, "turing-api-abc123") + t.Setenv(envPodNamespace, "test-namespace") + + assert.Equal(t, map[string]string{}, buildTags(config.PyroscopeConfig{IncludePodTags: false})) + }) + + t.Run("merges in CustomTags", func(t *testing.T) { + assert.Equal(t, map[string]string{"team": "fraud", "env": "staging"}, buildTags(config.PyroscopeConfig{ + CustomTags: map[string]string{"team": "fraud", "env": "staging"}, + })) + }) + + t.Run("built-in pod tags win over a colliding CustomTags key", func(t *testing.T) { + t.Setenv(envPodName, "turing-api-abc123") + + assert.Equal(t, map[string]string{"pod_name": "turing-api-abc123"}, buildTags(config.PyroscopeConfig{ + IncludePodTags: true, + CustomTags: map[string]string{"pod_name": "should-be-overridden"}, + })) + }) +} diff --git a/api/turing/service/router_deployment_service_test.go b/api/turing/service/router_deployment_service_test.go index ca3975b81..45366ba8a 100644 --- a/api/turing/service/router_deployment_service_test.go +++ b/api/turing/service/router_deployment_service_test.go @@ -119,7 +119,7 @@ func (msb *mockClusterServiceBuilder) NewRouterService( Name: fmt.Sprintf("%s-router-%d", rv.Router.Name, rv.Version), Namespace: project.Name, Envs: []corev1.EnvVar{ - {Name: "JAEGER_EP", Value: routerDefaults.JaegerCollectorEndpoint}, + {Name: "JAEGER_EP", Value: routerDefaults.JaegerCollectorEndpoint}, //nolint:staticcheck {Name: "FLUENTD_TAG", Value: routerDefaults.FluentdConfig.Tag}, {Name: "ENVIRONMENT", Value: envType}, {Name: "SENTRY_ENABLED", Value: strconv.FormatBool(sentryEnabled)}, @@ -306,7 +306,7 @@ func TestDeployEndpoint(t *testing.T) { Name: fmt.Sprintf("%s-router-%d", routerVersion.Router.Name, routerVersion.Version), Namespace: testNamespace, Envs: []corev1.EnvVar{ - {Name: "JAEGER_EP", Value: ds.routerDefaults.JaegerCollectorEndpoint}, + {Name: "JAEGER_EP", Value: ds.routerDefaults.JaegerCollectorEndpoint}, //nolint:staticcheck {Name: "FLUENTD_TAG", Value: ds.routerDefaults.FluentdConfig.Tag}, {Name: "ENVIRONMENT", Value: envType}, {Name: "SENTRY_ENABLED", Value: "true"}, diff --git a/api/turing/validation/validator.go b/api/turing/validation/validator.go index 1071f7bf9..87b0799a5 100644 --- a/api/turing/validation/validator.go +++ b/api/turing/validation/validator.go @@ -377,7 +377,7 @@ func validateRouterConfig(sl validator.StructLevel) { } // Validate dangling routes and traffic rules orthogonality checks - if router.TrafficRules != nil && len(router.TrafficRules) > 0 { + if len(router.TrafficRules) > 0 { checkDanglingRoutes(sl, "Routes", router.Routes, allRuleRoutesSet) validateConditionOrthogonality(sl, "TrafficRules", router.TrafficRules) } diff --git a/engines/experiment/Makefile b/engines/experiment/Makefile index 09582c62f..84f191103 100644 --- a/engines/experiment/Makefile +++ b/engines/experiment/Makefile @@ -7,7 +7,7 @@ default: test setup: @echo "Setting up tools..." @test -x $(shell go env GOPATH)/bin/golangci-lint || \ - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/v1.48.0/install.sh | sh -s -- -b $(shell go env GOPATH)/bin v1.48.0 + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/v2.12.2/install.sh | sh -s -- -b $(shell go env GOPATH)/bin v2.12.2 .PHONY: tidy tidy: diff --git a/engines/experiment/examples/plugins/hardcoded/Dockerfile b/engines/experiment/examples/plugins/hardcoded/Dockerfile index d95426512..886afabce 100644 --- a/engines/experiment/examples/plugins/hardcoded/Dockerfile +++ b/engines/experiment/examples/plugins/hardcoded/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.22-alpine as builder +FROM golang:1.25-alpine as builder ARG binary_name="plugin" ARG project_root=github.com/caraml-dev/turing/engines/experiment/examples/plugins/hardcoded/cmd diff --git a/engines/experiment/examples/plugins/hardcoded/go.mod b/engines/experiment/examples/plugins/hardcoded/go.mod index 8ac98aad0..bcd43c091 100644 --- a/engines/experiment/examples/plugins/hardcoded/go.mod +++ b/engines/experiment/examples/plugins/hardcoded/go.mod @@ -1,12 +1,12 @@ module github.com/caraml-dev/turing/engines/experiment/examples/plugins/hardcoded -go 1.22 +go 1.25 require ( github.com/caraml-dev/mlp v1.12.0 github.com/caraml-dev/turing/engines/experiment v1.0.0 github.com/hashicorp/go-hclog v1.5.0 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.9.0 ) require ( @@ -14,15 +14,15 @@ require ( github.com/buger/jsonparser v1.1.1 // indirect github.com/caraml-dev/turing/engines/router v0.0.0 // indirect github.com/caraml-dev/universal-prediction-interface v0.3.6 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.15.0 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/validator v9.31.0+incompatible // indirect github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect github.com/hashicorp/go-plugin v1.4.3 // indirect github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect github.com/leodido/go-urn v1.2.1 // indirect @@ -41,12 +41,14 @@ require ( github.com/zaffka/zap-to-hclog v0.10.6 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.11.0 // indirect - golang.org/x/text v0.7.0 // indirect - google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 // indirect - google.golang.org/grpc v1.52.3 // indirect - google.golang.org/protobuf v1.29.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/grpc v1.61.1 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/errgo.v2 v2.1.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/engines/experiment/examples/plugins/hardcoded/go.sum b/engines/experiment/examples/plugins/hardcoded/go.sum index 83b2ba911..f50529a40 100644 --- a/engines/experiment/examples/plugins/hardcoded/go.sum +++ b/engines/experiment/examples/plugins/hardcoded/go.sum @@ -19,8 +19,9 @@ github.com/caraml-dev/mlp v1.12.0/go.mod h1:Zdz4bALO9WOHXhOgsoLmCjMCJnDVEZEnQFg8 github.com/caraml-dev/universal-prediction-interface v0.3.6 h1:G/D4aukfjLECl8armJqFy/R2+0u/f4AiurSFqAo33uQ= github.com/caraml-dev/universal-prediction-interface v0.3.6/go.mod h1:e0qmFOXQxx8HFg5ObYyQO3WVnrqsr5v5JApFmeF7eJo= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -48,8 +49,6 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4= github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -63,19 +62,19 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.2 h1:BqHID5W5qnMkug0Z8UmL8tN0gAy4jQ+B4WFt8cCgluU= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.2/go.mod h1:ZbS3MZTZq/apAfAEHGoB5HbsQQstoqP92SjAqtQ9zeg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= @@ -97,6 +96,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -130,8 +131,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -159,23 +158,22 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g= +github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -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/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/zaffka/zap-to-hclog v0.10.6 h1:dNxbL5drL6sVUDHtCMbokJLWrYn5wSKAWTXjgWFadx0= github.com/zaffka/zap-to-hclog v0.10.6/go.mod h1:wLqRe/Fa1MkfUY9EtnCDiz2CqhTPNZPh0/pRE9lLi04= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= @@ -201,8 +199,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -232,13 +230,13 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/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= @@ -250,14 +248,18 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 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-20230131230820-1c016267d619 h1:p0kMzw6AG0JEzd7Z+kXqOiLhC6gjUQTbtS2zR0Q3DbI= -google.golang.org/genproto v0.0.0-20230131230820-1c016267d619/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 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.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ= -google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= 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= @@ -266,14 +268,14 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 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.29.0 h1:44S3JjaKmLEE4YIkjzexaP+NzZsudE3Zin5Njn/pYX0= -google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= diff --git a/engines/experiment/go.mod b/engines/experiment/go.mod index d1e168ef5..d485a7c2a 100644 --- a/engines/experiment/go.mod +++ b/engines/experiment/go.mod @@ -1,6 +1,6 @@ module github.com/caraml-dev/turing/engines/experiment -go 1.22 +go 1.25 require ( bou.ke/monkey v1.0.2 @@ -14,43 +14,44 @@ require ( github.com/mitchellh/hashstructure/v2 v2.0.2 github.com/mitchellh/mapstructure v1.5.0 github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.8.1 + github.com/stretchr/testify v1.9.0 github.com/zaffka/zap-to-hclog v0.10.6 go.uber.org/zap v1.26.0 - google.golang.org/grpc v1.52.3 + google.golang.org/grpc v1.61.1 ) require ( github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.15.0 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect github.com/mitchellh/go-testing-interface v1.0.0 // indirect - github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/oklog/run v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.11.1 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect github.com/prometheus/procfs v0.6.0 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/rogpeppe/go-internal v1.16.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/sys v0.11.0 // indirect - golang.org/x/text v0.7.0 // indirect - google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 // indirect - google.golang.org/protobuf v1.29.0 // indirect - gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/errgo.v2 v2.1.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/engines/experiment/go.sum b/engines/experiment/go.sum index 83b2ba911..f50529a40 100644 --- a/engines/experiment/go.sum +++ b/engines/experiment/go.sum @@ -19,8 +19,9 @@ github.com/caraml-dev/mlp v1.12.0/go.mod h1:Zdz4bALO9WOHXhOgsoLmCjMCJnDVEZEnQFg8 github.com/caraml-dev/universal-prediction-interface v0.3.6 h1:G/D4aukfjLECl8armJqFy/R2+0u/f4AiurSFqAo33uQ= github.com/caraml-dev/universal-prediction-interface v0.3.6/go.mod h1:e0qmFOXQxx8HFg5ObYyQO3WVnrqsr5v5JApFmeF7eJo= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +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/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -48,8 +49,6 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4= github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -63,19 +62,19 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/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.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.2 h1:BqHID5W5qnMkug0Z8UmL8tN0gAy4jQ+B4WFt8cCgluU= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.2/go.mod h1:ZbS3MZTZq/apAfAEHGoB5HbsQQstoqP92SjAqtQ9zeg= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= @@ -97,6 +96,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -130,8 +131,6 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -159,23 +158,22 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g= +github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -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/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/zaffka/zap-to-hclog v0.10.6 h1:dNxbL5drL6sVUDHtCMbokJLWrYn5wSKAWTXjgWFadx0= github.com/zaffka/zap-to-hclog v0.10.6/go.mod h1:wLqRe/Fa1MkfUY9EtnCDiz2CqhTPNZPh0/pRE9lLi04= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= @@ -201,8 +199,8 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -232,13 +230,13 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/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= @@ -250,14 +248,18 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 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-20230131230820-1c016267d619 h1:p0kMzw6AG0JEzd7Z+kXqOiLhC6gjUQTbtS2zR0Q3DbI= -google.golang.org/genproto v0.0.0-20230131230820-1c016267d619/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= 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.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ= -google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= 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= @@ -266,14 +268,14 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 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.29.0 h1:44S3JjaKmLEE4YIkjzexaP+NzZsudE3Zin5Njn/pYX0= -google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= diff --git a/engines/router/.env.development b/engines/router/.env.development index 9e7bd3a9e..3a87e67b2 100644 --- a/engines/router/.env.development +++ b/engines/router/.env.development @@ -33,10 +33,17 @@ APP_KAFKA_SERIALIZATION_FORMAT=json # Instrumentation APP_CUSTOM_METRICS=true +# Deprecated: classic Jaeger/Thrift backend. Use APP_OTEL_* instead unless a +# specific downstream backend still requires Thrift ingestion. APP_JAEGER_ENABLED=false -APP_JAEGER_COLLECTOR_ENDPOINT= +APP_JAEGER_COLLECTOR_ENDPOINT=http://localhost:14268/api/traces APP_JAEGER_REPORTER_HOST=localhost APP_JAEGER_REPORTER_PORT=6831 +APP_OTEL_ENABLED=false +APP_OTEL_COLLECTOR_ENDPOINT=http://localhost:4318 +APP_OTEL_SAMPLING_RATIO=1 +APP_PYROSCOPE_ENABLED=false +APP_PYROSCOPE_SERVER_ADDRESS=http://localhost:4040 SENTRY_ENABLED=false SENTRY_DSN= diff --git a/engines/router/Dockerfile b/engines/router/Dockerfile index bc98fd9ee..57121ecb9 100644 --- a/engines/router/Dockerfile +++ b/engines/router/Dockerfile @@ -1,5 +1,5 @@ # Build application binary -FROM golang:1.22-alpine as builder +FROM golang:1.25-alpine as builder ARG BIN_NAME=turing-router ARG VERSION ARG USER diff --git a/engines/router/Makefile b/engines/router/Makefile index 87ad4fae8..29341074a 100644 --- a/engines/router/Makefile +++ b/engines/router/Makefile @@ -21,7 +21,7 @@ clean: .PHONY: setup setup: @echo "Setting up tools..." - @test -x ${GOPATH}/bin/golangci-lint || go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.51.2 + @test -x ${GOPATH}/bin/golangci-lint || go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2 @test -x $(shell go env GOPATH)/bin/gotest || go install github.com/rakyll/gotest@latest .PHONY: fmt diff --git a/engines/router/README.md b/engines/router/README.md index a72b0ab6d..06e64ffb3 100644 --- a/engines/router/README.md +++ b/engines/router/README.md @@ -66,7 +66,7 @@ __Note:__ The app uses the `in_forward` plugin to write data to a TCP socket. - name: TEST_ENV2 value: value2 ``` -3. Jaeger client is initialised to trace all requests (`const` mode). However, the tracer's `IsEnabled()` methods determine whether the app adds the trace to the requests. To run Jaeger locally, do `make jaeger-local`. Simulating incoming requests with Spans: +3. OpenTelemetry (`APP_OTEL_*`) is now the primary tracer; the classic Jaeger/Thrift backend described below (`APP_JAEGER_*`) is deprecated and kept only for downstream backends that still require Thrift ingestion. Jaeger client is initialised to trace all requests (`const` mode). However, the tracer's `IsEnabled()` methods determine whether the app adds the trace to the requests. To run Jaeger locally, do `make jaeger-local`. Simulating incoming requests with Spans: ``` curl -v -X GET http://localhost:8080/v1/predict \ -H "X-B3-Sampled: 1" \ diff --git a/engines/router/compose/tracing.yaml b/engines/router/compose/tracing.yaml index be124df3a..b99a2d854 100644 --- a/engines/router/compose/tracing.yaml +++ b/engines/router/compose/tracing.yaml @@ -3,6 +3,18 @@ version: '3.1' services: jaeger: image: jaegertracing/all-in-one:latest + environment: + - COLLECTOR_OTLP_ENABLED=true ports: + # 6831/udp and 14268 are for the classic, deprecated Jaeger/Thrift ingestion + # (used by APP_JAEGER_*). 4317/4318 are OTLP gRPC/HTTP, used by APP_OTEL_*. - 6831:6831/udp + - 14268:14268 - 16686:16686 + - 4317:4317 + - 4318:4318 + + pyroscope: + image: grafana/pyroscope:latest + ports: + - 4040:4040 diff --git a/engines/router/go.mod b/engines/router/go.mod index 06ab3b3e6..572668d9d 100644 --- a/engines/router/go.mod +++ b/engines/router/go.mod @@ -1,10 +1,10 @@ module github.com/caraml-dev/turing/engines/router -go 1.22 +go 1.25 require ( bou.ke/monkey v1.0.2 - cloud.google.com/go/bigquery v1.44.0 + cloud.google.com/go/bigquery v1.57.1 github.com/buger/jsonparser v1.1.1 github.com/caraml-dev/mlp v1.12.0 github.com/caraml-dev/turing/engines/experiment v0.0.0 @@ -13,55 +13,77 @@ require ( github.com/go-playground/validator/v10 v10.11.1 github.com/gojek/fiber v0.2.1-rc2 github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 - github.com/google/go-cmp v0.5.9 - github.com/google/uuid v1.3.0 + github.com/google/go-cmp v0.6.0 + github.com/google/uuid v1.4.0 + github.com/grafana/pyroscope-go v1.2.0 github.com/heptiolabs/healthcheck v0.0.0-20180807145615-6ff867650f40 github.com/json-iterator/go v1.1.12 github.com/kelseyhightower/envconfig v1.4.0 - github.com/opentracing/opentracing-go v1.1.0 + github.com/opentracing/opentracing-go v1.2.0 github.com/pierrec/lz4 v2.4.1+incompatible github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.11.1 github.com/soheilhy/cmux v0.1.5 - github.com/stretchr/testify v1.8.1 - github.com/uber/jaeger-client-go v2.23.1+incompatible + github.com/stretchr/testify v1.9.0 + github.com/uber/jaeger-client-go v2.30.0+incompatible go.einride.tech/protobuf-bigquery v0.7.0 + go.opentelemetry.io/contrib/propagators/b3 v1.24.0 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 + go.opentelemetry.io/otel/trace v1.24.0 go.uber.org/zap v1.26.0 - google.golang.org/grpc v1.52.3 - google.golang.org/protobuf v1.29.0 + google.golang.org/grpc v1.61.1 + google.golang.org/protobuf v1.32.0 gopkg.in/confluentinc/confluent-kafka-go.v1 v1.4.2 ) require ( - cloud.google.com/go v0.107.0 // indirect - cloud.google.com/go/compute v1.14.0 // indirect + cloud.google.com/go v0.111.0 // indirect + cloud.google.com/go/compute v1.23.3 // indirect cloud.google.com/go/compute/metadata v0.2.3 // indirect - cloud.google.com/go/iam v0.8.0 // indirect + cloud.google.com/go/iam v1.1.5 // indirect + github.com/andybalholm/brotli v1.0.4 // indirect + github.com/apache/arrow/go/v12 v12.0.0 // indirect + github.com/apache/thrift v0.16.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/confluentinc/confluent-kafka-go v1.4.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/fatih/color v1.15.0 // indirect github.com/frankban/quicktest v1.8.1 // indirect github.com/getsentry/raven-go v0.2.0 // indirect github.com/ghodss/yaml v1.0.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/validator v9.31.0+incompatible // indirect + github.com/goccy/go-json v0.9.11 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.1 // indirect - github.com/googleapis/gax-go/v2 v2.7.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/flatbuffers v2.0.8+incompatible // indirect + github.com/google/s2a-go v0.1.7 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect + github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/grafana/pyroscope-go/godeltaprof v0.1.8 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect github.com/hashicorp/go-hclog v1.5.0 // indirect github.com/hashicorp/go-plugin v1.4.3 // indirect github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d // indirect + github.com/klauspost/asmfmt v1.3.2 // indirect + github.com/klauspost/compress v1.17.8 // indirect + github.com/klauspost/cpuid/v2 v2.0.9 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 // indirect + github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 // indirect github.com/mitchellh/go-testing-interface v1.0.0 // indirect github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect @@ -69,26 +91,36 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/oklog/run v1.0.0 // indirect github.com/philhofer/fwd v1.0.0 // indirect + github.com/pierrec/lz4/v4 v4.1.15 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.26.0 // indirect github.com/prometheus/procfs v0.6.0 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/tinylib/msgp v1.1.2 // indirect - github.com/uber/jaeger-lib v2.2.0+incompatible // indirect + github.com/uber/jaeger-lib v2.0.0+incompatible // indirect github.com/zaffka/zap-to-hclog v0.10.6 // indirect + github.com/zeebo/xxh3 v1.0.2 // indirect go.opencensus.io v0.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/otel/metric v1.24.0 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.5.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/oauth2 v0.5.0 // indirect - golang.org/x/sys v0.11.0 // indirect - golang.org/x/text v0.7.0 // indirect + golang.org/x/crypto v0.16.0 // indirect + golang.org/x/mod v0.10.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/oauth2 v0.15.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/tools v0.9.1 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect - google.golang.org/api v0.106.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 // indirect + google.golang.org/api v0.149.0 // indirect + google.golang.org/appengine v1.6.8 // indirect + google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 // indirect gopkg.in/errgo.v2 v2.1.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/engines/router/go.sum b/engines/router/go.sum index b3652f534..8ce4e9f63 100644 --- a/engines/router/go.sum +++ b/engines/router/go.sum @@ -17,8 +17,8 @@ cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOY cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.107.0 h1:qkj22L7bgkl6vIeZDlOY2po43Mx/TIa2Wsa7VR+PEww= -cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= +cloud.google.com/go v0.111.0 h1:YHLKNupSD1KqjDbQ3+LVdQ81h/UJbJyZG203cEfnQgM= +cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -26,20 +26,20 @@ cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUM cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= cloud.google.com/go/bigquery v1.14.0/go.mod h1:5W5fTMEyY+JxNqHenf5atJFqt0lqylyG+pIHyJYH4c8= -cloud.google.com/go/bigquery v1.44.0 h1:Wi4dITi+cf9VYp4VH2T9O41w0kCW0uQTELq2Z6tukN0= -cloud.google.com/go/bigquery v1.44.0/go.mod h1:0Y33VqXTEsbamHJvJHdFmtqHvMIY28aK1+dFsvaChGc= -cloud.google.com/go/compute v1.14.0 h1:hfm2+FfxVmnRlh6LpB7cg1ZNU+5edAHmW679JePztk0= -cloud.google.com/go/compute v1.14.0/go.mod h1:YfLtxrj9sU4Yxv+sXzZkyPjEyPBZfXHUvjxega5vAdo= +cloud.google.com/go/bigquery v1.57.1 h1:FiULdbbzUxWD0Y4ZGPSVCDLvqRSyCIO6zKV7E2nf5uA= +cloud.google.com/go/bigquery v1.57.1/go.mod h1:iYzC0tGVWt1jqSzBHqCr3lrRn0u13E8e+AqowBsDgug= +cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= +cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= 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/datacatalog v1.8.0 h1:6kZ4RIOW/uT7QWC5SfPfq/G8sYzr/v+UOmOAxy4Z1TE= -cloud.google.com/go/datacatalog v1.8.0/go.mod h1:KYuoVOv9BM8EYz/4eMFxrr4DUKhGIOXxZoKYF5wdISM= +cloud.google.com/go/datacatalog v1.19.0 h1:rbYNmHwvAOOwnW2FPXYkaK3Mf1MmGqRzK0mMiIEyLdo= +cloud.google.com/go/datacatalog v1.19.0/go.mod h1:5FR6ZIF8RZrtml0VUao22FxhdjkoG+a0866rEnObryM= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v0.8.0 h1:E2osAkZzxI/+8pZcxVLcDtAQx/u+hZXVryUaYQ5O0Kk= -cloud.google.com/go/iam v0.8.0/go.mod h1:lga0/y3iH6CX7sYqypWJ33hf7kkfXJag67naqGESjkE= -cloud.google.com/go/longrunning v0.3.0 h1:NjljC+FYPV3uh5/OwWT6pVU+doBqMg2x/rZlE+CamDs= -cloud.google.com/go/longrunning v0.3.0/go.mod h1:qth9Y41RRSUE69rDcOn6DdK3HfQfsUI0YSmW3iIlLJc= +cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= +cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= +cloud.google.com/go/longrunning v0.5.4 h1:w8xEcbZodnA2BbW6sVirkkoC+1gP8wS57EUUgGS0GVg= +cloud.google.com/go/longrunning v0.5.4/go.mod h1:zqNVncI0BOP8ST6XQD1+VcvuShMmq7+xFSzOL++V0dI= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -49,16 +49,24 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.29.0 h1:6weCgzRvMg7lzuUurI4697AqIRPU1SvzHhynwpW31jI= -cloud.google.com/go/storage v1.29.0/go.mod h1:4puEjyTKnku6gfKoTfNOU/W+a9JyuVNxjpS5GBrB8h4= +cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM= +cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU= +github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c/go.mod h1:X0CRv0ky0k6m906ixxpzmDRLvX58TFUKS2eePweuyxk= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/apache/arrow/go/v12 v12.0.0 h1:xtZE63VWl7qLdB0JObIXvvhGjoVNrQ9ciIHG2OK5cmc= +github.com/apache/arrow/go/v12 v12.0.0/go.mod h1:d+tV/eHZZ7Dz7RPrFKtPK02tpr+c9/PEd/zm8mDS9Vg= +github.com/apache/thrift v0.16.0 h1:qEy6UW60iVOlUy+b9ZR0d5WzUWYGOo4HfopoyBaNmoY= +github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -71,11 +79,14 @@ github.com/caraml-dev/mlp v1.12.0 h1:yb/EgMh+83oKj0C1AhH3R6xt0eSd9GX+incZEOwM7oo github.com/caraml-dev/mlp v1.12.0/go.mod h1:Zdz4bALO9WOHXhOgsoLmCjMCJnDVEZEnQFg8rk+u2cE= github.com/caraml-dev/universal-prediction-interface v0.3.6 h1:G/D4aukfjLECl8armJqFy/R2+0u/f4AiurSFqAo33uQ= github.com/caraml-dev/universal-prediction-interface v0.3.6/go.mod h1:e0qmFOXQxx8HFg5ObYyQO3WVnrqsr5v5JApFmeF7eJo= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40 h1:xvUo53O5MRZhVMJAxWCJcS5HHrqAiAG9SJ1LpMu6aAI= github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +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/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -116,6 +127,11 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= @@ -127,14 +143,14 @@ github.com/go-playground/validator v9.31.0+incompatible/go.mod h1:yrEkQXlcI+Pugk github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= +github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gojek/fiber v0.2.1-rc2 h1:hJPaH4jDlIBhfRKQby2CISPnbSh7vx5S996IvuXA34U= github.com/gojek/fiber v0.2.1-rc2/go.mod h1:R5cRkUnXdTLpdchCkm3lmGJS+nfhPhLDOklRq1T65Jg= github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4= github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= -github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -147,6 +163,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 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= @@ -162,10 +179,15 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= +github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= 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= @@ -177,15 +199,15 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= +github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -196,17 +218,23 @@ github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= +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/googleapis/enterprise-certificate-proxy v0.2.1 h1:RY7tHKZcRlk788d5WSo/e83gOyyy742E8GSs771ySpg= -github.com/googleapis/enterprise-certificate-proxy v0.2.1/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k= +github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= +github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= +github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ= -github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.2 h1:BqHID5W5qnMkug0Z8UmL8tN0gAy4jQ+B4WFt8cCgluU= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.2/go.mod h1:ZbS3MZTZq/apAfAEHGoB5HbsQQstoqP92SjAqtQ9zeg= +github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= +github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/grafana/pyroscope-go v1.2.0 h1:aILLKjTj8CS8f/24OPMGPewQSYlhmdQMBmol1d3KGj8= +github.com/grafana/pyroscope-go v1.2.0/go.mod h1:2GHr28Nr05bg2pElS+dDsc98f3JTUh2f6Fz1hWXrqwk= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8 h1:iwOtYXeeVSAeYefJNaxDytgjKtUuKQbJqgAIjlnicKg= +github.com/grafana/pyroscope-go/godeltaprof v0.1.8/go.mod h1:2+l7K7twW49Ct4wFluZD3tZ6e0SjanjcUUBPVD/UuGU= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU= github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-hclog v1.5.0 h1:bI2ocEMgcVlz55Oj1xZNBsVi900c7II+fWDyV9o+13c= github.com/hashicorp/go-hclog v1.5.0/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= @@ -237,14 +265,21 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8 github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= +github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= +github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= +github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -265,6 +300,10 @@ github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APP github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs= +github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8/go.mod h1:mC1jAcsrzbxHt8iiaC+zU4b1ylILSosueou12R++wfY= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3 h1:+n/aFZefKZp7spd8DFdX7uMikMLXX4oubIzJF4kv/wI= +github.com/minio/c2goasm v0.0.0-20190812172519-36a3d3bbc4f3/go.mod h1:RagcQ7I8IeTMnF8JTXieKnO4Z6JCsikNEzj0DwauVzE= github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= @@ -283,12 +322,14 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= -github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= -github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v2.4.1+incompatible h1:mFe7ttWaflA46Mhqh+jUfjp2qTbPYxLB2/OyBppH9dg= github.com/pierrec/lz4 v2.4.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0= +github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -317,8 +358,9 @@ github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3x github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.16.0 h1:O9DK+vNMDVGLr2BeZqmpLeMjiMNkuXfcqntWbZV6S5g= +github.com/rogpeppe/go-internal v1.16.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -328,8 +370,9 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -339,20 +382,26 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/uber/jaeger-client-go v2.23.1+incompatible h1:uArBYHQR0HqLFFAypI7RsWTzPSj/bDpmZZuQjMLSg1A= -github.com/uber/jaeger-client-go v2.23.1+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= -github.com/uber/jaeger-lib v2.2.0+incompatible h1:MxZXOiR2JuoANZ3J6DE/U0kSFv/eJ/GfSYVCjK7dyaw= -github.com/uber/jaeger-lib v2.2.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= +github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= +github.com/uber/jaeger-lib v2.0.0+incompatible h1:iMSCV0rmXEogjNWPh2D0xk9YVKvrtGoHJNe9ebLu/pw= +github.com/uber/jaeger-lib v2.0.0+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zaffka/zap-to-hclog v0.10.6 h1:dNxbL5drL6sVUDHtCMbokJLWrYn5wSKAWTXjgWFadx0= github.com/zaffka/zap-to-hclog v0.10.6/go.mod h1:wLqRe/Fa1MkfUY9EtnCDiz2CqhTPNZPh0/pRE9lLi04= +github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= +github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0= +github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA= go.einride.tech/protobuf-bigquery v0.7.0 h1:8OIyEW/vl2BEBCXYek0f0Gy1OLAWbCVOiKjSMgKWzZ4= go.einride.tech/protobuf-bigquery v0.7.0/go.mod h1:Nw3+OrRBOXaIwucZF9kZt8gydxGv7kX+Zb6cXGvHKos= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -363,6 +412,22 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.opentelemetry.io/contrib/propagators/b3 v1.24.0 h1:n4xwCdTx3pZqZs2CjS/CUZAs03y3dZcGhC/FepKtEUY= +go.opentelemetry.io/contrib/propagators/b3 v1.24.0/go.mod h1:k5wRxKRU2uXx2F8uNJ4TaonuEO/V7/5xoz7kdsDACT8= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= @@ -377,9 +442,10 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 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-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= +golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -390,6 +456,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= +golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -412,6 +480,9 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= +golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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= @@ -446,9 +517,11 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +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.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -457,8 +530,8 @@ golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= -golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= +golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ= +golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -469,6 +542,9 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -515,11 +591,14 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -528,8 +607,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/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.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -579,12 +659,17 @@ golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201204162204-73cf035baebf/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo= +golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +gonum.org/v1/gonum v0.11.0 h1:f1IJhK4Km5tBJmaiJXtk/PkL4cdVX6J+tGiM187uT5E= +gonum.org/v1/gonum v0.11.0/go.mod h1:fSG4YDCxxUZQJ7rKsQrj0gMOg00Il0Z96/qMA4bVQhA= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -603,16 +688,17 @@ google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSr google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.106.0 h1:ffmW0faWCwKkpbbtvlY/K/8fUl+JKvNS5CVzRoyfCv8= -google.golang.org/api v0.106.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= +google.golang.org/api v0.149.0 h1:b2CqT6kG+zqJIVKRQ3ELJVLN1PwHZ6DJ3dW8yl82rgY= +google.golang.org/api v0.149.0/go.mod h1:Mwn1B7JTXrzXtnvmzQE2BD6bYZQ8DShKZDZbeN9I7qI= 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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -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/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= +google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -648,8 +734,12 @@ google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201204160425-06b3db808446/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20230131230820-1c016267d619 h1:p0kMzw6AG0JEzd7Z+kXqOiLhC6gjUQTbtS2zR0Q3DbI= -google.golang.org/genproto v0.0.0-20230131230820-1c016267d619/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0 h1:YJ5pD9rF8o9Qtta0Cmy9rdBwkSjrTCT6XTiUQVOtIos= +google.golang.org/genproto v0.0.0-20231212172506-995d672761c0/go.mod h1:l/k7rMz0vFTBPy+tFSGvXEd3z+BcoG1k7EHbqm+YBsY= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= +google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917 h1:6G8oQ016D88m1xAKljMlBOOGWDZkes4kMhgGFlf8WcQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240102182953-50ed04b92917/go.mod h1:xtjpI3tXFPP051KaWnhvxkiubL/6dJ18vLVf7q2pTOU= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -666,8 +756,8 @@ google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.52.3 h1:pf7sOysg4LdgBqduXveGKrcEwbStiK2rtfghdzlUYDQ= -google.golang.org/grpc v1.52.3/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= 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= @@ -680,8 +770,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 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.29.0 h1:44S3JjaKmLEE4YIkjzexaP+NzZsudE3Zin5Njn/pYX0= -google.golang.org/protobuf v1.29.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0 h1:FVCohIoYO7IJoDDVpV2pdq7SgrMH6wHnuTyrdrxJNoY= gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0/go.mod h1:OdE7CF6DbADk7lN8LIKRzRJTTZXIjtWgA5THM5lhBAw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/engines/router/missionctl/config/config.go b/engines/router/missionctl/config/config.go index 9650e849a..37d0a24bd 100644 --- a/engines/router/missionctl/config/config.go +++ b/engines/router/missionctl/config/config.go @@ -110,15 +110,49 @@ type KafkaConfig struct { CompressionType string `split_words:"true" default:"none"` } -// JaegerConfig captures the settings for tracing using Jaeger client -// Ref: https://pkg.go.dev/github.com/uber/jaeger-client-go/config +// JaegerConfig captures the settings for tracing using the classic Jaeger client +// (OpenTracing API, Thrift transport over a UDP agent or an HTTP collector). +// +// Deprecated: Jaeger's native Thrift ingestion is being phased out; use OtelConfig +// instead unless a specific downstream backend still requires Thrift. This config, +// and the tracer backend it configures, will be removed in a future release. type JaegerConfig struct { - Enabled bool + Enabled bool + // CollectorEndpoint is a Thrift-over-HTTP Jaeger collector endpoint, + // e.g. http://jaeger-collector:14268/api/traces CollectorEndpoint string `split_words:"true"` ReporterAgentHost string `envconfig:"REPORTER_HOST" split_words:"true"` ReporterAgentPort int `envconfig:"REPORTER_PORT" split_words:"true"` } +// OtelConfig captures the settings for tracing using OpenTelemetry, exported via OTLP HTTP. +type OtelConfig struct { + Enabled bool + // CollectorEndpoint is the OTLP HTTP endpoint spans are exported to, + // e.g. http://otel-collector:4318 + CollectorEndpoint string `split_words:"true"` + // SamplingRatio is the fraction of traces to sample, between 0 and 1. Defaults to 0.01. + SamplingRatio float64 `split_words:"true" default:"0.01"` +} + +// PyroscopeConfig captures the settings for continuous profiling using Pyroscope +type PyroscopeConfig struct { + Enabled bool + ServerAddress string `split_words:"true"` + // HTTPHeaders are attached to every profile push request, e.g. for auth + // (Authorization, X-Scope-OrgID, ...). Optional. + HTTPHeaders map[string]string `split_words:"true"` + // CustomTags are additional static tags attached to every profile, on top of the + // always-present router_name tag (and pod_name/pod_namespace, when IncludePodTags is + // true). If a key collides with one of those built-in tags, the built-in value wins. + // Optional. + CustomTags map[string]string `split_words:"true"` + // IncludePodTags controls whether profiles are additionally tagged with pod_name/ + // pod_namespace (from the POD_NAME/POD_NAMESPACE downward API env vars), on top of the + // always-present router_name tag. Defaults to true. + IncludePodTags bool `split_words:"true" default:"true"` +} + // AppConfig is the structure used to the parse the environment configs that correspond // to application behavior such as logging, instrumentation, etc. type AppConfig struct { @@ -134,7 +168,9 @@ type AppConfig struct { BigQuery *BQConfig `envconfig:"BQ"` Fluentd *FluentdConfig Kafka *KafkaConfig - Jaeger *JaegerConfig + Jaeger *JaegerConfig // Deprecated: see JaegerConfig. + Otel *OtelConfig + Pyroscope *PyroscopeConfig Sentry sentry.Config } diff --git a/engines/router/missionctl/config/config_test.go b/engines/router/missionctl/config/config_test.go index 2d82cd087..7588c666f 100644 --- a/engines/router/missionctl/config/config_test.go +++ b/engines/router/missionctl/config/config_test.go @@ -7,6 +7,7 @@ import ( "github.com/caraml-dev/mlp/api/pkg/instrumentation/sentry" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" tu "github.com/caraml-dev/turing/engines/router/missionctl/internal/testutils" ) @@ -58,9 +59,14 @@ var optionalEnvs = map[string]string{ "APP_KAFKA_TOPIC": "kafka_topic", "APP_KAFKA_SERIALIZATION_FORMAT": "json", "APP_JAEGER_ENABLED": "true", - "APP_JAEGER_COLLECTOR_ENDPOINT": "http://localhost:5000", + "APP_JAEGER_COLLECTOR_ENDPOINT": "http://localhost:14268/api/traces", "APP_JAEGER_REPORTER_HOST": "localhost", - "APP_JAEGER_REPORTER_PORT": "5001", + "APP_JAEGER_REPORTER_PORT": "6831", + "APP_OTEL_ENABLED": "true", + "APP_OTEL_COLLECTOR_ENDPOINT": "http://localhost:5000", + "APP_OTEL_SAMPLING_RATIO": "0.8", + "APP_PYROSCOPE_ENABLED": "true", + "APP_PYROSCOPE_SERVER_ADDRESS": "http://localhost:4040", "APP_SENTRY_ENABLED": "true", "APP_SENTRY_DSN": "test:dsn", "APP_SENTRY_LABELS": "sentry_key1:value1,sentry_key2:value2", @@ -122,6 +128,16 @@ func TestInitConfigDefaultEnvs(t *testing.T) { ReporterAgentHost: "", ReporterAgentPort: 0, }, + Otel: &OtelConfig{ + Enabled: false, + CollectorEndpoint: "", + SamplingRatio: 0.01, + }, + Pyroscope: &PyroscopeConfig{ + Enabled: false, + ServerAddress: "", + IncludePodTags: true, + }, Sentry: sentry.Config{ Enabled: false, DSN: "", @@ -182,9 +198,19 @@ func TestInitConfigEnv(t *testing.T) { CustomMetrics: true, Jaeger: &JaegerConfig{ Enabled: true, - CollectorEndpoint: "http://localhost:5000", + CollectorEndpoint: "http://localhost:14268/api/traces", ReporterAgentHost: "localhost", - ReporterAgentPort: 5001, + ReporterAgentPort: 6831, + }, + Otel: &OtelConfig{ + Enabled: true, + CollectorEndpoint: "http://localhost:5000", + SamplingRatio: 0.8, + }, + Pyroscope: &PyroscopeConfig{ + Enabled: true, + ServerAddress: "http://localhost:4040", + IncludePodTags: true, }, Sentry: sentry.Config{ Enabled: true, @@ -345,6 +371,45 @@ func TestSerializationFormatDecode(t *testing.T) { } } +func TestInitConfigEnv_JaegerOtelAndPyroscope(t *testing.T) { + env := map[string]string{ + "PORT": "8080", + "ROUTER_CONFIG_FILE": "config.yaml", + "APP_NAME": "test-router", + "APP_ENVIRONMENT": "dev", + "APP_JAEGER_ENABLED": "true", + "APP_JAEGER_COLLECTOR_ENDPOINT": "http://localhost:14268/api/traces", + "APP_JAEGER_REPORTER_HOST": "localhost", + "APP_JAEGER_REPORTER_PORT": "6831", + "APP_OTEL_ENABLED": "true", + "APP_OTEL_COLLECTOR_ENDPOINT": "http://otel-collector:4318", + "APP_OTEL_SAMPLING_RATIO": "0.5", + "APP_PYROSCOPE_ENABLED": "true", + "APP_PYROSCOPE_SERVER_ADDRESS": "http://pyroscope:4040", + "APP_PYROSCOPE_HTTP_HEADERS": "Authorization:Bearer token,X-Scope-OrgID:tenant1", + "APP_PYROSCOPE_INCLUDE_POD_TAGS": "false", + } + setupNewEnv(env) + + cfg, err := InitConfigEnv() + require.NoError(t, err) + + assert.Equal(t, true, cfg.AppConfig.Jaeger.Enabled) + assert.Equal(t, "http://localhost:14268/api/traces", cfg.AppConfig.Jaeger.CollectorEndpoint) + assert.Equal(t, "localhost", cfg.AppConfig.Jaeger.ReporterAgentHost) + assert.Equal(t, 6831, cfg.AppConfig.Jaeger.ReporterAgentPort) + assert.Equal(t, true, cfg.AppConfig.Otel.Enabled) + assert.Equal(t, "http://otel-collector:4318", cfg.AppConfig.Otel.CollectorEndpoint) + assert.Equal(t, 0.5, cfg.AppConfig.Otel.SamplingRatio) + assert.Equal(t, true, cfg.AppConfig.Pyroscope.Enabled) + assert.Equal(t, "http://pyroscope:4040", cfg.AppConfig.Pyroscope.ServerAddress) + assert.Equal(t, map[string]string{ + "Authorization": "Bearer token", + "X-Scope-OrgID": "tenant1", + }, cfg.AppConfig.Pyroscope.HTTPHeaders) + assert.Equal(t, false, cfg.AppConfig.Pyroscope.IncludePodTags) +} + func setupNewEnv(envMaps ...map[string]string) { os.Clearenv() diff --git a/engines/router/missionctl/errors/errors_test.go b/engines/router/missionctl/errors/errors_test.go index 30636d1b4..8f907396d 100644 --- a/engines/router/missionctl/errors/errors_test.go +++ b/engines/router/missionctl/errors/errors_test.go @@ -2,7 +2,6 @@ package errors import ( "errors" - "fmt" "net/http" "testing" @@ -89,7 +88,7 @@ func TestGetHTTPErrorCode(t *testing.T) { func TestNewHTTPErrorMessage(t *testing.T) { message := "Test Error Message" - err := fmt.Errorf(message) + err := errors.New(message) httpErr := NewTuringError(err, fiberProtocol.HTTP) assert.Equal(t, message, httpErr.Error()) } @@ -114,7 +113,7 @@ func TestNewHTTPErrorStatus(t *testing.T) { t.Run(name, func(t *testing.T) { // Create new error message := "Test Error" - err := fmt.Errorf(message) + err := errors.New(message) // Create new HTTP error httpErr := NewTuringError(err, fiberProtocol.HTTP, data.codes...) // Validate diff --git a/engines/router/missionctl/fiberapi/fan_in.go b/engines/router/missionctl/fiberapi/fan_in.go index 07cfc802f..55b9550b1 100644 --- a/engines/router/missionctl/fiberapi/fan_in.go +++ b/engines/router/missionctl/fiberapi/fan_in.go @@ -10,7 +10,7 @@ import ( "github.com/gojek/fiber" fiberHttp "github.com/gojek/fiber/http" jsoniter "github.com/json-iterator/go" - "github.com/opentracing/opentracing-go" + "go.opentelemetry.io/otel/trace" "github.com/caraml-dev/turing/engines/router/missionctl/instrumentation" @@ -113,10 +113,10 @@ func (fanIn *EnsemblingFanIn) Aggregate( // Associate span to context to trace response ensembling, if tracing enabled if tracing.Glob().IsEnabled() { - var sp opentracing.Span + var sp trace.Span sp, _ = tracing.Glob().StartSpanFromContext(ctx, FanInID) if sp != nil { - defer sp.Finish() + defer sp.End() } } return fanIn.collectResponses(responses, experimentResponse) diff --git a/engines/router/missionctl/fiberapi/interceptors.go b/engines/router/missionctl/fiberapi/interceptors.go index b895fed9b..ed7edc7c2 100644 --- a/engines/router/missionctl/fiberapi/interceptors.go +++ b/engines/router/missionctl/fiberapi/interceptors.go @@ -6,7 +6,7 @@ import ( "time" "github.com/gojek/fiber" - "github.com/opentracing/opentracing-go" + "go.opentelemetry.io/otel/trace" "github.com/caraml-dev/turing/engines/router/missionctl/instrumentation" @@ -199,14 +199,12 @@ func (i *TracingInterceptor) BeforeDispatch( return ctx } -// AfterCompletion retrieves the span from the context, if exists, and finishes the trace +// AfterCompletion retrieves the span from the context and finishes it. If no span was +// associated with the context, this is a no-op (trace.SpanFromContext never returns nil). func (i *TracingInterceptor) AfterCompletion( ctx context.Context, _ fiber.Request, _ fiber.ResponseQueue, ) { - span := opentracing.SpanFromContext(ctx) - if span != nil { - span.Finish() - } + trace.SpanFromContext(ctx).End() } diff --git a/engines/router/missionctl/fiberapi/interceptors_test.go b/engines/router/missionctl/fiberapi/interceptors_test.go index 03efa4250..00e18d4ab 100644 --- a/engines/router/missionctl/fiberapi/interceptors_test.go +++ b/engines/router/missionctl/fiberapi/interceptors_test.go @@ -10,15 +10,15 @@ import ( "testing" "time" - "bou.ke/monkey" "github.com/gojek/fiber" fiberHttp "github.com/gojek/fiber/http" - "github.com/opentracing/opentracing-go" - opentracingLog "github.com/opentracing/opentracing-go/log" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/sdk/trace/tracetest" + "go.opentelemetry.io/otel/trace" - "github.com/caraml-dev/turing/engines/router/missionctl/config" "github.com/caraml-dev/turing/engines/router/missionctl/instrumentation/tracing" tu "github.com/caraml-dev/turing/engines/router/missionctl/internal/testutils" "github.com/caraml-dev/turing/engines/router/missionctl/log" @@ -96,50 +96,25 @@ func (*mockMetricsCollector) Inc( return nil } -// mockSpan satisfies the opentracing.Span interface -type mockSpan struct { - mock.Mock -} - -func (s *mockSpan) Finish() { - s.Called() -} -func (*mockSpan) FinishWithOptions(_ opentracing.FinishOptions) {} -func (*mockSpan) Context() opentracing.SpanContext { return nil } -func (*mockSpan) SetOperationName(_ string) opentracing.Span { return nil } -func (*mockSpan) SetTag(_ string, _ interface{}) opentracing.Span { return nil } -func (*mockSpan) LogFields(_ ...opentracingLog.Field) {} -func (*mockSpan) LogKV(_ ...interface{}) {} -func (*mockSpan) SetBaggageItem(_, _ string) opentracing.Span { return nil } -func (*mockSpan) BaggageItem(_ string) string { return "" } -func (*mockSpan) Tracer() opentracing.Tracer { return nil } -func (*mockSpan) LogEvent(_ string) {} -func (*mockSpan) LogEventWithPayload(_ string, _ interface{}) {} -func (*mockSpan) Log(_ opentracing.LogData) {} - // mockTracer implements tracing.Tracer interface type mockTracer struct { mock.Mock } -func (*mockTracer) IsEnabled() bool { return false } -func (*mockTracer) SetEnabled(_ bool) {} +func (*mockTracer) IsEnabled() bool { return false } func (*mockTracer) StartSpanFromRequestHeader( - context.Context, - string, - http.Header, -) (opentracing.Span, context.Context) { - return nil, nil + ctx context.Context, + _ string, + _ http.Header, +) (trace.Span, context.Context) { + return nil, ctx } func (t *mockTracer) StartSpanFromContext( ctx context.Context, name string, -) (opentracing.Span, context.Context) { +) (trace.Span, context.Context) { t.Called(ctx, name) - return nil, nil -} -func (*mockTracer) InitGlobalTracer(_ string, _ *config.JaegerConfig) (io.Closer, error) { - return io.NopCloser(nil), nil + return nil, ctx } // Test that a startTimeKey has been associated to the context @@ -354,24 +329,19 @@ func TestTracingInterceptorBeforeDispatch(t *testing.T) { } func TestTracingInterceptorAfterCompletion(t *testing.T) { - // Create mock span - mockSp := &mockSpan{} - mockSp.On("Finish").Return(nil) - - // Patch opentracing.SpanFromContext to return the mock span - monkey.Patch(opentracing.SpanFromContext, - func(_ context.Context) opentracing.Span { - return mockSp - }) - defer monkey.Unpatch(opentracing.SpanFromContext) + exporter := tracetest.NewInMemoryExporter() + tp := sdktrace.NewTracerProvider(sdktrace.WithSyncer(exporter)) + tr := tp.Tracer("test") + + ctx, span := tr.Start(context.Background(), "test-span") + _ = span - // Run Test i := NewTracingInterceptor() - _, ctx := opentracing.StartSpanFromContext(context.Background(), "test") i.AfterCompletion(ctx, nil, nil) - // Validate that mockSpan.Finish() has been called - mockSp.AssertCalled(t, "Finish") + spans := exporter.GetSpans() + require.Len(t, spans, 1) + assert.Equal(t, "test-span", spans[0].Name) } func createTestFiberResponseQueue(respStatus int) fiber.ResponseQueue { diff --git a/engines/router/missionctl/instrumentation/profiling/profiling.go b/engines/router/missionctl/instrumentation/profiling/profiling.go new file mode 100644 index 000000000..ed26769d5 --- /dev/null +++ b/engines/router/missionctl/instrumentation/profiling/profiling.go @@ -0,0 +1,75 @@ +package profiling + +import ( + "fmt" + "os" + + "github.com/grafana/pyroscope-go" + + "github.com/caraml-dev/turing/engines/router/missionctl/config" +) + +const ( + applicationName = "turing-router" + // envPodName and envPodNamespace are populated via the Kubernetes downward API by the + // Turing API's servicebuilder. They are absent when running outside a pod (e.g. local dev). + envPodName = "POD_NAME" + envPodNamespace = "POD_NAMESPACE" +) + +// Start starts continuous profiling via pyroscope-go if enabled in cfg. All router +// deployments report under the same Pyroscope application name and are differentiated +// by the router_name tag, plus -- when cfg.IncludePodTags is true -- pod_name/pod_namespace +// tags populated from the POD_NAME and POD_NAMESPACE downward API env vars, to distinguish +// individual pods within a multi-replica router deployment. The pod tags are also omitted +// when those env vars are unset, so as not to report noisy empty-string tags outside a real +// pod. cfg.CustomTags are merged in on top of those, though router_name/pod_name/ +// pod_namespace always win on key collision. Returns a nil profiler and nil error when +// profiling is disabled or cfg is nil. +// pyroscope.Start does not itself error on an empty ServerAddress -- it happily constructs a +// client that fails silently on every upload -- so an empty address is rejected explicitly +// here instead. +func Start(routerName string, cfg *config.PyroscopeConfig) (*pyroscope.Profiler, error) { + if cfg == nil || !cfg.Enabled { + return nil, nil + } + if cfg.ServerAddress == "" { + return nil, fmt.Errorf("pyroscope profiling is enabled but ServerAddress is empty") + } + + return pyroscope.Start(pyroscope.Config{ + ApplicationName: applicationName, + ServerAddress: cfg.ServerAddress, + HTTPHeaders: cfg.HTTPHeaders, + Tags: buildTags(routerName, cfg.CustomTags, cfg.IncludePodTags), + ProfileTypes: []pyroscope.ProfileType{ + pyroscope.ProfileCPU, + pyroscope.ProfileAllocObjects, + pyroscope.ProfileAllocSpace, + pyroscope.ProfileInuseObjects, + pyroscope.ProfileInuseSpace, + pyroscope.ProfileGoroutines, + }, + }) +} + +// buildTags returns the static Pyroscope tags for this process: customTags first, then +// router_name always, plus pod_name/pod_namespace -- when includePodTags is true -- for +// whichever of the corresponding downward API env vars are set. router_name/pod_name/ +// pod_namespace are applied last, so they always win over a colliding customTags key. +func buildTags(routerName string, customTags map[string]string, includePodTags bool) map[string]string { + tags := make(map[string]string, len(customTags)+3) + for k, v := range customTags { + tags[k] = v + } + tags["router_name"] = routerName + if includePodTags { + if podName := os.Getenv(envPodName); podName != "" { + tags["pod_name"] = podName + } + if podNamespace := os.Getenv(envPodNamespace); podNamespace != "" { + tags["pod_namespace"] = podNamespace + } + } + return tags +} diff --git a/engines/router/missionctl/instrumentation/profiling/profiling_internal_test.go b/engines/router/missionctl/instrumentation/profiling/profiling_internal_test.go new file mode 100644 index 000000000..3a9dfbcce --- /dev/null +++ b/engines/router/missionctl/instrumentation/profiling/profiling_internal_test.go @@ -0,0 +1,51 @@ +package profiling + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBuildTags(t *testing.T) { + t.Run("only router_name when pod env vars are unset", func(t *testing.T) { + assert.Equal(t, map[string]string{"router_name": "test-router"}, buildTags("test-router", nil, true)) + }) + + t.Run("includes pod_name and pod_namespace when set and includePodTags is true", func(t *testing.T) { + t.Setenv(envPodName, "test-router-abc123") + t.Setenv(envPodNamespace, "test-namespace") + + assert.Equal(t, map[string]string{ + "router_name": "test-router", + "pod_name": "test-router-abc123", + "pod_namespace": "test-namespace", + }, buildTags("test-router", nil, true)) + }) + + t.Run("omits pod_name and pod_namespace when includePodTags is false, even if set", func(t *testing.T) { + t.Setenv(envPodName, "test-router-abc123") + t.Setenv(envPodNamespace, "test-namespace") + + assert.Equal(t, map[string]string{"router_name": "test-router"}, buildTags("test-router", nil, false)) + }) + + t.Run("merges in customTags", func(t *testing.T) { + assert.Equal(t, map[string]string{ + "router_name": "test-router", + "team": "fraud", + "env": "staging", + }, buildTags("test-router", map[string]string{"team": "fraud", "env": "staging"}, true)) + }) + + t.Run("built-in tags win over a colliding customTags key", func(t *testing.T) { + t.Setenv(envPodName, "test-router-abc123") + + assert.Equal(t, map[string]string{ + "router_name": "test-router", + "pod_name": "test-router-abc123", + }, buildTags("test-router", map[string]string{ + "router_name": "should-be-overridden", + "pod_name": "should-also-be-overridden", + }, true)) + }) +} diff --git a/engines/router/missionctl/instrumentation/profiling/profiling_test.go b/engines/router/missionctl/instrumentation/profiling/profiling_test.go new file mode 100644 index 000000000..a7cdb3b97 --- /dev/null +++ b/engines/router/missionctl/instrumentation/profiling/profiling_test.go @@ -0,0 +1,53 @@ +package profiling_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/caraml-dev/turing/engines/router/missionctl/config" + "github.com/caraml-dev/turing/engines/router/missionctl/instrumentation/profiling" +) + +func TestStart_Disabled(t *testing.T) { + profiler, err := profiling.Start("test-router", &config.PyroscopeConfig{Enabled: false}) + require.NoError(t, err) + assert.Nil(t, profiler) +} + +func TestStart_NilConfig(t *testing.T) { + profiler, err := profiling.Start("test-router", nil) + require.NoError(t, err) + assert.Nil(t, profiler) +} + +func TestStart_Enabled(t *testing.T) { + profiler, err := profiling.Start("test-router", &config.PyroscopeConfig{ + Enabled: true, + ServerAddress: "http://localhost:4040", + }) + require.NoError(t, err) + require.NotNil(t, profiler) + defer func() { _ = profiler.Stop() }() +} + +func TestStart_EnabledWithHTTPHeaders(t *testing.T) { + profiler, err := profiling.Start("test-router", &config.PyroscopeConfig{ + Enabled: true, + ServerAddress: "http://localhost:4040", + HTTPHeaders: map[string]string{"Authorization": "Bearer token"}, + }) + require.NoError(t, err) + require.NotNil(t, profiler) + defer func() { _ = profiler.Stop() }() +} + +func TestStart_EnabledEmptyServerAddress(t *testing.T) { + profiler, err := profiling.Start("test-router", &config.PyroscopeConfig{ + Enabled: true, + ServerAddress: "", + }) + require.Error(t, err) + assert.Nil(t, profiler) +} diff --git a/engines/router/missionctl/instrumentation/tracing/jaeger.go b/engines/router/missionctl/instrumentation/tracing/jaeger.go index 3d73ee04a..541bba8e9 100644 --- a/engines/router/missionctl/instrumentation/tracing/jaeger.go +++ b/engines/router/missionctl/instrumentation/tracing/jaeger.go @@ -1,29 +1,86 @@ package tracing import ( + "context" "fmt" - "io" + "net/http" - "github.com/opentracing/opentracing-go" + ot "github.com/opentracing/opentracing-go" + otext "github.com/opentracing/opentracing-go/ext" + jaeger "github.com/uber/jaeger-client-go" jaegercfg "github.com/uber/jaeger-client-go/config" - "github.com/uber/jaeger-client-go/zipkin" + + "go.opentelemetry.io/contrib/propagators/b3" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/trace" + "go.opentelemetry.io/otel/trace/embedded" + "go.opentelemetry.io/otel/trace/noop" "github.com/caraml-dev/turing/engines/router/missionctl/config" ) -// JaegerTracer implements the Tracer interface using the jaeger client library +// JaegerTracer implements the Tracer interface using the classic Jaeger client +// library (OpenTracing API, Thrift transport over a UDP agent or an HTTP +// collector). Every trace.Tracer/trace.Span call made by the rest of this +// codebase is translated into the equivalent ot.Tracer/ot.Span (OpenTracing) +// call by this file, so spans are still physically created by the classic +// Jaeger client and exported over Thrift, while callers keep working against +// the same trace.Span type regardless of which backend is active. +// +// Note: go.opentelemetry.io/otel/bridge/opentracing only bridges in the +// opposite direction to what's needed here -- it forwards OpenTracing-API +// calls onto an OpenTelemetry trace.Tracer of choice (see its NewTracerPair, +// which takes a trace.Tracer, not an ot.Tracer), so it cannot adapt an +// existing ot.Tracer (the classic Jaeger client) into a trace.Tracer. This +// file does that translation directly instead. +// +// Deprecated: this backend exists only to support downstream systems that +// still require Jaeger's native Thrift ingestion; it will be removed in a +// future release. New deployments should use OtelTracer (OtelConfig) instead. type JaegerTracer struct { - *baseTracer + tracer ot.Tracer + propagator propagation.TextMapPropagator } -// InitGlobalTracer creates a global tracer using the Jaeger client -func (t *JaegerTracer) InitGlobalTracer(name string, cfg *config.JaegerConfig) (io.Closer, error) { +// newJaegerTracer builds a classic Jaeger client from cfg (sampling all requests, +// matching this backend's pre-OTel-migration behaviour, and generating 128-bit +// trace IDs so they line up byte-for-byte with the OTel trace.TraceID format used +// elsewhere in this codebase), and returns a Tracer that adapts it to the +// trace.Tracer/trace.Span API, alongside a ShutdownFunc that closes the underlying +// Jaeger reporter. +func newJaegerTracer(name string, cfg *config.JaegerConfig) (Tracer, ShutdownFunc, error) { //nolint:staticcheck + jCfg := jaegercfg.Configuration{ + ServiceName: name, + Disabled: !cfg.Enabled, + Gen128Bit: true, + Reporter: &jaegercfg.ReporterConfig{ + CollectorEndpoint: cfg.CollectorEndpoint, + LocalAgentHostPort: fmt.Sprintf("%s:%d", cfg.ReporterAgentHost, cfg.ReporterAgentPort), + LogSpans: true, + }, + Sampler: &jaegercfg.SamplerConfig{ + Type: "const", + Param: 1, + }, + } - // Create a zipkin propagator as the HTTP extractor - zipkinPropagator := zipkin.NewZipkinB3HTTPHeaderPropagator() - // Initialize tracer with the default logger - return buildConfig(cfg).InitGlobalTracer(name, - jaegercfg.Extractor(opentracing.HTTPHeaders, zipkinPropagator)) + nativeTracer, closer, err := jCfg.NewTracer() + if err != nil { + return nil, nil, err + } + + t := &JaegerTracer{ + tracer: nativeTracer, + // Reuse the same propagator OtelTracer uses for incoming header extraction, + // so both backends agree on how a remote parent span context is decoded. + propagator: propagation.NewCompositeTextMapPropagator( + propagation.TraceContext{}, propagation.Baggage{}, b3.New(), + ), + } + + return t, func(context.Context) error { return closer.Close() }, nil } // IsEnabled satisfies the Tracer interface, always returning true @@ -31,28 +88,164 @@ func (*JaegerTracer) IsEnabled() bool { return true } -// buildConfig converts the input JaegerConfig into the format that can be interpreted -// by the Jaeger client library, applying const sampling -func buildConfig(jCfg *config.JaegerConfig) jaegercfg.Configuration { - return jaegercfg.Configuration{ - Disabled: !jCfg.Enabled, - Reporter: &jaegercfg.ReporterConfig{ - CollectorEndpoint: jCfg.CollectorEndpoint, - LocalAgentHostPort: fmt.Sprintf("%s:%d", - jCfg.ReporterAgentHost, jCfg.ReporterAgentPort), - LogSpans: true, - }, - // Sample all requests by default. - Sampler: &jaegercfg.SamplerConfig{ - Type: "const", - Param: 1, - }, +// StartSpanFromRequestHeader extracts a remote span context from the request header +// and starts a child span from it. +func (t *JaegerTracer) StartSpanFromRequestHeader( + ctx context.Context, + opName string, + header http.Header, +) (trace.Span, context.Context) { + ctx = t.propagator.Extract(ctx, propagation.HeaderCarrier(header)) + return t.startSpan(ctx, opName) +} + +// StartSpanFromContext starts a new / child span associated with the given context. +func (t *JaegerTracer) StartSpanFromContext( + ctx context.Context, + opName string, +) (trace.Span, context.Context) { + return t.startSpan(ctx, opName) +} + +// startSpan starts a native Jaeger span, using whatever OTel trace.SpanContext is +// already present in ctx (either injected by StartSpanFromRequestHeader above, or +// left there by a previous call to this same JaegerTracer) as its ChildOf parent, +// so the classic Jaeger client's own trace/span IDs stay derived from -- and thus +// consistent with -- the trace.SpanContext exposed to the rest of this codebase. +func (t *JaegerTracer) startSpan(ctx context.Context, opName string) (trace.Span, context.Context) { + var opts []ot.StartSpanOption + if parent := trace.SpanContextFromContext(ctx); parent.IsValid() { + if parentSC, err := jaegerSpanContextFrom(parent); err == nil { + opts = append(opts, ot.ChildOf(parentSC)) + } + } + + span := &jaegerSpan{span: t.tracer.StartSpan(opName, opts...)} + return span, trace.ContextWithSpan(ctx, span) +} + +// jaegerSpanContextFrom converts an OTel trace.SpanContext into the equivalent +// jaeger.SpanContext, so a span started from an OTel-style parent (extracted from +// request headers, or carried over from a previous jaegerSpan already in ctx) +// keeps the same trace ID under the classic Jaeger client too. +func jaegerSpanContextFrom(sc trace.SpanContext) (jaeger.SpanContext, error) { + traceID, err := jaeger.TraceIDFromString(sc.TraceID().String()) + if err != nil { + return jaeger.SpanContext{}, err + } + spanID, err := jaeger.SpanIDFromString(sc.SpanID().String()) + if err != nil { + return jaeger.SpanContext{}, err + } + return jaeger.NewSpanContext(traceID, spanID, 0, sc.IsSampled(), nil), nil +} + +// jaegerSpan adapts a native Jaeger (OpenTracing) ot.Span to the OTel trace.Span +// interface, so every backend in this package exposes the same span type to callers. +type jaegerSpan struct { + embedded.Span + + span ot.Span +} + +// End satisfies trace.Span, finishing the underlying native Jaeger span. +func (s *jaegerSpan) End(...trace.SpanEndOption) { + s.span.Finish() +} + +// AddEvent satisfies trace.Span, logging name and any attributes as a structured +// log entry on the underlying native Jaeger span. +func (s *jaegerSpan) AddEvent(name string, options ...trace.EventOption) { + cfg := trace.NewEventConfig(options...) + attrs := cfg.Attributes() + + kv := make([]interface{}, 0, 2+2*len(attrs)) + kv = append(kv, "event", name) + for _, attr := range attrs { + kv = append(kv, string(attr.Key), attr.Value.AsInterface()) + } + s.span.LogKV(kv...) +} + +// IsRecording satisfies trace.Span. The classic Jaeger client does not expose +// whether a given span will actually be sampled/reported until Finish(), so this +// conservatively always returns true. +func (s *jaegerSpan) IsRecording() bool { + return true +} + +// RecordError satisfies trace.Span, tagging the underlying native Jaeger span as +// an error and logging err on it. +func (s *jaegerSpan) RecordError(err error, _ ...trace.EventOption) { + otext.LogError(s.span, err) +} + +// SpanContext satisfies trace.Span, translating the underlying native Jaeger +// span's own SpanContext into the equivalent OTel trace.SpanContext. +func (s *jaegerSpan) SpanContext() trace.SpanContext { + sc, ok := s.span.Context().(jaeger.SpanContext) + if !ok { + return trace.SpanContext{} + } + + // jaeger.TraceID.String() only zero-pads to 32 hex chars when High != 0 (i.e. + // when the trace was actually generated as 128-bit); pad it out so it always + // parses as a valid OTel TraceID. + traceIDHex := sc.TraceID().String() + for len(traceIDHex) < 32 { + traceIDHex = "0" + traceIDHex + } + + traceID, err := trace.TraceIDFromHex(traceIDHex) + if err != nil { + return trace.SpanContext{} + } + spanID, err := trace.SpanIDFromHex(sc.SpanID().String()) + if err != nil { + return trace.SpanContext{} } + + var flags trace.TraceFlags + if sc.IsSampled() { + flags = trace.FlagsSampled + } + + return trace.NewSpanContext(trace.SpanContextConfig{ + TraceID: traceID, + SpanID: spanID, + TraceFlags: flags, + }) } -// newJaegerTracer is a creator for the Jaeger Tracer -func newJaegerTracer() Tracer { - return &JaegerTracer{ - &baseTracer{}, +// SetStatus satisfies trace.Span, tagging the underlying native Jaeger span with +// the OTel status code/description. +func (s *jaegerSpan) SetStatus(code codes.Code, description string) { + if code == codes.Error { + s.span.SetTag("error", true) + } + s.span.SetTag("otel.status_code", code.String()) + if description != "" { + s.span.SetTag("otel.status_description", description) } } + +// SetName satisfies trace.Span, changing the underlying native Jaeger span's +// operation name. +func (s *jaegerSpan) SetName(name string) { + s.span.SetOperationName(name) +} + +// SetAttributes satisfies trace.Span, setting each attribute as a tag on the +// underlying native Jaeger span. +func (s *jaegerSpan) SetAttributes(kv ...attribute.KeyValue) { + for _, attr := range kv { + s.span.SetTag(string(attr.Key), attr.Value.AsInterface()) + } +} + +// TracerProvider satisfies trace.Span. This backend doesn't construct an OTel +// SDK TracerProvider (spans are created directly against the native Jaeger +// ot.Tracer), so this returns a no-op provider. +func (s *jaegerSpan) TracerProvider() trace.TracerProvider { + return noop.NewTracerProvider() +} diff --git a/engines/router/missionctl/instrumentation/tracing/jaeger_test.go b/engines/router/missionctl/instrumentation/tracing/jaeger_test.go index eef7bd150..9cd19125a 100644 --- a/engines/router/missionctl/instrumentation/tracing/jaeger_test.go +++ b/engines/router/missionctl/instrumentation/tracing/jaeger_test.go @@ -5,71 +5,73 @@ import ( "net/http" "testing" - "github.com/opentracing/opentracing-go" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/caraml-dev/turing/engines/router/missionctl/config" ) -func TestIsEnabled(t *testing.T) { - tr := newJaegerTracer() +func TestNewJaegerTracer_IsEnabled(t *testing.T) { + tr, shutdown, err := newJaegerTracer("test", &config.JaegerConfig{ //nolint:staticcheck + Enabled: true, + ReporterAgentHost: "localhost", + ReporterAgentPort: 6831, + }) + require.NoError(t, err) + defer func() { _ = shutdown(context.Background()) }() + assert.Equal(t, true, tr.IsEnabled()) } -func TestStartSpanFromRequestHeader(t *testing.T) { - tr := newJaegerTracer() - - // Init global tracer using Jaeger client - _, _ = tr.InitGlobalTracer("test", &config.JaegerConfig{ +func TestNewJaegerTracer_StartSpanFromContext(t *testing.T) { + tr, shutdown, err := newJaegerTracer("test", &config.JaegerConfig{ //nolint:staticcheck Enabled: true, ReporterAgentHost: "localhost", - ReporterAgentPort: 6832, + ReporterAgentPort: 6831, }) + require.NoError(t, err) + defer func() { _ = shutdown(context.Background()) }() - // Set span related attributes to request header - header := http.Header{} - header.Set("X-B3-Sampled", "1") - header.Set("X-B3-Spanid", "a30ec88c39471716") - header.Set("X-B3-Traceid", "950f2de0b8430e9fa30ec88c39471716") - header.Set("X-Request-Id", "26787b1c-bf6e-97a8-8b30-36675e4effa0") - - // Verify that a span can be extracted and a child span created - sp, _ := tr.StartSpanFromRequestHeader(context.Background(), "test", header) - assert.NotNil(t, sp) + span, ctx := tr.StartSpanFromContext(context.Background(), "test-op") + assert.NotNil(t, span) + assert.NotNil(t, ctx) + span.End() } -func TestStartSpanFromContext(t *testing.T) { - tr := newJaegerTracer() - - // Init global tracer using Jaeger client - _, _ = tr.InitGlobalTracer("test", &config.JaegerConfig{ +func TestNewJaegerTracer_NestedSpans_ShareTraceID(t *testing.T) { + tr, shutdown, err := newJaegerTracer("test", &config.JaegerConfig{ //nolint:staticcheck Enabled: true, ReporterAgentHost: "localhost", - ReporterAgentPort: 6832, + ReporterAgentPort: 6831, }) + require.NoError(t, err) + defer func() { _ = shutdown(context.Background()) }() + + outerSpan, ctx := tr.StartSpanFromContext(context.Background(), "outer") + innerSpan, _ := tr.StartSpanFromContext(ctx, "inner") - // Associate a new span to a context - _, ctx := opentracing.StartSpanFromContext(context.Background(), "test") - // Verify that a span can be extracted and a child span created - sp, _ := tr.StartSpanFromContext(ctx, "test") - assert.NotNil(t, sp) + assert.Equal(t, outerSpan.SpanContext().TraceID(), innerSpan.SpanContext().TraceID()) + innerSpan.End() + outerSpan.End() } -func TestBuildConfig(t *testing.T) { - cfg := &config.JaegerConfig{ +func TestNewJaegerTracer_StartSpanFromRequestHeader(t *testing.T) { + tr, shutdown, err := newJaegerTracer("test", &config.JaegerConfig{ //nolint:staticcheck Enabled: true, ReporterAgentHost: "localhost", - ReporterAgentPort: 2000, - CollectorEndpoint: "test_endpoint", - } + ReporterAgentPort: 6831, + }) + require.NoError(t, err) + defer func() { _ = shutdown(context.Background()) }() - jaegerCfg := buildConfig(cfg) + header := http.Header{} + header.Set("X-B3-Traceid", "4bf92f3577b34da6a3ce929d0e0e4736") + header.Set("X-B3-Spanid", "00f067aa0ba902b7") + header.Set("X-B3-Sampled", "1") - // Test jaeger config values - assert.Equal(t, false, jaegerCfg.Disabled) - assert.Equal(t, "test_endpoint", jaegerCfg.Reporter.CollectorEndpoint) - assert.Equal(t, "localhost:2000", jaegerCfg.Reporter.LocalAgentHostPort) - assert.Equal(t, true, jaegerCfg.Reporter.LogSpans) - assert.Equal(t, "const", jaegerCfg.Sampler.Type) - assert.Equal(t, float64(1), jaegerCfg.Sampler.Param) + span, ctx := tr.StartSpanFromRequestHeader(context.Background(), "test-op", header) + assert.NotNil(t, span) + assert.NotNil(t, ctx) + assert.Equal(t, "4bf92f3577b34da6a3ce929d0e0e4736", span.SpanContext().TraceID().String()) + span.End() } diff --git a/engines/router/missionctl/instrumentation/tracing/multi.go b/engines/router/missionctl/instrumentation/tracing/multi.go new file mode 100644 index 000000000..fb4696d9e --- /dev/null +++ b/engines/router/missionctl/instrumentation/tracing/multi.go @@ -0,0 +1,145 @@ +package tracing + +import ( + "context" + "net/http" + + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/codes" + "go.opentelemetry.io/otel/trace" + "go.opentelemetry.io/otel/trace/embedded" +) + +// MultiTracer fans out span creation to every wrapped Tracer, so a single logical +// operation is exported to all of them. Used when more than one backend is enabled +// simultaneously (e.g. both JaegerConfig and OtelConfig). +type MultiTracer struct { + tracers []Tracer +} + +// newMultiTracer wraps tracers (expected to have at least 2 elements -- for exactly +// one enabled backend, InitGlobalTracer uses it directly instead) in a MultiTracer. +func newMultiTracer(tracers []Tracer) Tracer { + return &MultiTracer{tracers: tracers} +} + +// IsEnabled satisfies the Tracer interface, always returning true (MultiTracer is +// only constructed when at least one wrapped tracer is enabled). +func (*MultiTracer) IsEnabled() bool { + return true +} + +// multiParentsKey is the context key under which each backend's own previous span +// is tracked independently (see multiSpan's doc comment for why a single shared +// composite identity can't be used for this). +type multiParentsKey struct{} + +// StartSpanFromContext starts a span on every wrapped tracer, each parented from +// its OWN previous span (tracked independently per backend via multiParentsKey, +// not the shared composite -- see multiSpan's doc comment for why that matters), +// and returns a composite span representing all of them. +func (m *MultiTracer) StartSpanFromContext(ctx context.Context, opName string) (trace.Span, context.Context) { + parents, _ := ctx.Value(multiParentsKey{}).([]trace.Span) + spans := make([]trace.Span, len(m.tracers)) + for i, t := range m.tracers { + backendCtx := ctx + // Guard against a length mismatch (e.g. if SetGlob swapped the global tracer, + // changing the number of backends, mid-request): fall back to the plain ctx + // for this backend rather than panicking on an out-of-range index. + if parents != nil && len(parents) == len(m.tracers) { + backendCtx = trace.ContextWithSpan(ctx, parents[i]) + } + spans[i], _ = t.StartSpanFromContext(backendCtx, opName) + } + return m.newCompositeCtx(ctx, spans) +} + +// StartSpanFromRequestHeader starts a span on every wrapped tracer, each extracting +// its own remote parent from header, and returns a composite span representing all +// of them. (No multiParentsKey lookup needed here: this is always the root of a +// request, so there's no prior per-backend parent to seed each backendCtx with -- +// each backend independently extracts its own parent straight from header instead.) +func (m *MultiTracer) StartSpanFromRequestHeader( + ctx context.Context, + opName string, + header http.Header, +) (trace.Span, context.Context) { + spans := make([]trace.Span, len(m.tracers)) + for i, t := range m.tracers { + spans[i], _ = t.StartSpanFromRequestHeader(ctx, opName, header) + } + return m.newCompositeCtx(ctx, spans) +} + +// newCompositeCtx wraps spans in a multiSpan and seeds ctx with both the composite +// (for a caller's trace.SpanFromContext(ctx).End() to find) and the raw per-backend +// spans keyed by multiParentsKey (for the next nested call to hand each backend its +// own correct parent, per the doc comment above). +func (m *MultiTracer) newCompositeCtx(ctx context.Context, spans []trace.Span) (trace.Span, context.Context) { + composite := &multiSpan{spans: spans} + ctx = context.WithValue(ctx, multiParentsKey{}, spans) + return composite, trace.ContextWithSpan(ctx, composite) +} + +// multiSpan implements trace.Span by fanning every mutating call out to every +// wrapped span. SpanContext/IsRecording/TracerProvider delegate to the first +// wrapped span only -- but that is now purely about what identity the composite +// itself reports to any external caller that inspects it directly (e.g. logging +// the "current" trace ID). It no longer has anything to do with parent-chaining +// for a later nested StartSpanFromContext call: that lookup goes through +// multiParentsKey instead, precisely because delegating parent-lookup to spans[0] +// unconditionally would give every backend after the first the wrong parent (the +// first backend's span identity, not its own). +type multiSpan struct { + embedded.Span + + spans []trace.Span +} + +func (m *multiSpan) End(options ...trace.SpanEndOption) { + for _, s := range m.spans { + s.End(options...) + } +} + +func (m *multiSpan) AddEvent(name string, options ...trace.EventOption) { + for _, s := range m.spans { + s.AddEvent(name, options...) + } +} + +func (m *multiSpan) IsRecording() bool { + return m.spans[0].IsRecording() +} + +func (m *multiSpan) RecordError(err error, options ...trace.EventOption) { + for _, s := range m.spans { + s.RecordError(err, options...) + } +} + +func (m *multiSpan) SpanContext() trace.SpanContext { + return m.spans[0].SpanContext() +} + +func (m *multiSpan) SetStatus(code codes.Code, description string) { + for _, s := range m.spans { + s.SetStatus(code, description) + } +} + +func (m *multiSpan) SetName(name string) { + for _, s := range m.spans { + s.SetName(name) + } +} + +func (m *multiSpan) SetAttributes(kv ...attribute.KeyValue) { + for _, s := range m.spans { + s.SetAttributes(kv...) + } +} + +func (m *multiSpan) TracerProvider() trace.TracerProvider { + return m.spans[0].TracerProvider() +} diff --git a/engines/router/missionctl/instrumentation/tracing/multi_test.go b/engines/router/missionctl/instrumentation/tracing/multi_test.go new file mode 100644 index 000000000..77f1c1d46 --- /dev/null +++ b/engines/router/missionctl/instrumentation/tracing/multi_test.go @@ -0,0 +1,89 @@ +package tracing + +import ( + "context" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/sdk/trace/tracetest" + "go.opentelemetry.io/otel/trace" +) + +// recordingTracer is a minimal Tracer that records every span it starts via an +// in-memory exporter, so tests can assert on what a MultiTracer produced. +type recordingTracer struct { + tracer trace.Tracer + exporter *tracetest.InMemoryExporter +} + +func newRecordingTracer(name string) *recordingTracer { + exporter := tracetest.NewInMemoryExporter() + tp := sdktrace.NewTracerProvider(sdktrace.WithSyncer(exporter)) + return &recordingTracer{tracer: tp.Tracer(name), exporter: exporter} +} + +func (*recordingTracer) IsEnabled() bool { return true } + +func (r *recordingTracer) StartSpanFromContext(ctx context.Context, opName string) (trace.Span, context.Context) { + ctx, span := r.tracer.Start(ctx, opName) + return span, ctx +} + +func (r *recordingTracer) StartSpanFromRequestHeader( + ctx context.Context, + opName string, + _ http.Header, +) (trace.Span, context.Context) { + return r.StartSpanFromContext(ctx, opName) +} + +func TestMultiTracer_IsEnabled(t *testing.T) { + mt := newMultiTracer([]Tracer{newRecordingTracer("a"), newRecordingTracer("b")}) + assert.Equal(t, true, mt.IsEnabled()) +} + +func TestMultiTracer_StartSpanFromContext_RecordsOnEveryBackend(t *testing.T) { + a := newRecordingTracer("a") + b := newRecordingTracer("b") + mt := newMultiTracer([]Tracer{a, b}) + + span, ctx := mt.StartSpanFromContext(context.Background(), "test-op") + require.NotNil(t, span) + require.NotNil(t, ctx) + span.End() + + require.Len(t, a.exporter.GetSpans(), 1) + require.Len(t, b.exporter.GetSpans(), 1) + assert.Equal(t, "test-op", a.exporter.GetSpans()[0].Name) + assert.Equal(t, "test-op", b.exporter.GetSpans()[0].Name) +} + +func TestMultiTracer_NestedSpans_EachBackendKeepsItsOwnParentChain(t *testing.T) { + a := newRecordingTracer("a") + b := newRecordingTracer("b") + mt := newMultiTracer([]Tracer{a, b}) + + outerSpan, ctx := mt.StartSpanFromContext(context.Background(), "outer") + innerSpan, ctx := mt.StartSpanFromContext(ctx, "inner") + innerSpan.End() + outerSpan.End() + _ = ctx + + for _, exp := range []*tracetest.InMemoryExporter{a.exporter, b.exporter} { + spans := exp.GetSpans() + require.Len(t, spans, 2) + var outer, inner tracetest.SpanStub + for _, s := range spans { + if s.Name == "outer" { + outer = s + } else { + inner = s + } + } + assert.Equal(t, outer.SpanContext.SpanID(), inner.Parent.SpanID()) + assert.Equal(t, outer.SpanContext.TraceID(), inner.SpanContext.TraceID()) + } +} diff --git a/engines/router/missionctl/instrumentation/tracing/nop.go b/engines/router/missionctl/instrumentation/tracing/nop.go index 55f5bd928..dcdf020c5 100644 --- a/engines/router/missionctl/instrumentation/tracing/nop.go +++ b/engines/router/missionctl/instrumentation/tracing/nop.go @@ -2,44 +2,36 @@ package tracing import ( "context" - "io" "net/http" - "github.com/opentracing/opentracing-go" - - "github.com/caraml-dev/turing/engines/router/missionctl/config" + "go.opentelemetry.io/otel/trace" ) // NopTracer implements the Tracer interface with dummy methods type NopTracer struct{} -// InitGlobalTracer satisfies the Tracer interface and returns a Nop closer -func (*NopTracer) InitGlobalTracer(_ string, _ *config.JaegerConfig) (io.Closer, error) { - return io.NopCloser(nil), nil -} - // IsEnabled satisfies the Tracer interface, always returning false func (*NopTracer) IsEnabled() bool { return false } // StartSpanFromRequestHeader satisfies the Tracer interface, returning the context as -// is and an empty span +// is and a no-op span func (*NopTracer) StartSpanFromRequestHeader( ctx context.Context, _ string, _ http.Header, -) (opentracing.Span, context.Context) { - return nil, ctx +) (trace.Span, context.Context) { + return trace.SpanFromContext(ctx), ctx } // StartSpanFromContext satisfies the Tracer interface, returning the context as is -// and an empty span +// and a no-op span func (*NopTracer) StartSpanFromContext( ctx context.Context, _ string, -) (opentracing.Span, context.Context) { - return nil, ctx +) (trace.Span, context.Context) { + return trace.SpanFromContext(ctx), ctx } func newNopTracer() Tracer { diff --git a/engines/router/missionctl/instrumentation/tracing/nop_test.go b/engines/router/missionctl/instrumentation/tracing/nop_test.go index 50980becb..65bbcf79e 100644 --- a/engines/router/missionctl/instrumentation/tracing/nop_test.go +++ b/engines/router/missionctl/instrumentation/tracing/nop_test.go @@ -2,6 +2,7 @@ package tracing import ( "context" + "net/http" "testing" "github.com/stretchr/testify/assert" @@ -10,22 +11,13 @@ import ( func TestNopMethods(t *testing.T) { tr := newNopTracer() - // Create test context - testCtx := context.Background() - - // Test methods with return values assert.Equal(t, false, tr.IsEnabled()) - closer, err := tr.InitGlobalTracer("", nil) - assert.NoError(t, err) - err = closer.Close() - assert.NoError(t, err) - - sp, ctx := tr.StartSpanFromRequestHeader(testCtx, "", nil) - assert.Nil(t, sp) - assert.Equal(t, testCtx, ctx) + sp, ctx := tr.StartSpanFromRequestHeader(context.Background(), "test", http.Header{}) + assert.NotNil(t, sp) + assert.NotNil(t, ctx) - sp, ctx = tr.StartSpanFromContext(testCtx, "") - assert.Nil(t, sp) - assert.Equal(t, testCtx, ctx) + sp, ctx = tr.StartSpanFromContext(context.Background(), "test") + assert.NotNil(t, sp) + assert.NotNil(t, ctx) } diff --git a/engines/router/missionctl/instrumentation/tracing/otel.go b/engines/router/missionctl/instrumentation/tracing/otel.go new file mode 100644 index 000000000..92c2af13b --- /dev/null +++ b/engines/router/missionctl/instrumentation/tracing/otel.go @@ -0,0 +1,104 @@ +package tracing + +import ( + "context" + "fmt" + "net/http" + "net/url" + + "go.opentelemetry.io/contrib/propagators/b3" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/resource" + sdktrace "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/trace" + + "github.com/caraml-dev/turing/engines/router/missionctl/config" +) + +// OtelTracer implements the Tracer interface using the OpenTelemetry SDK, +// exporting spans via OTLP over HTTP. +type OtelTracer struct { + tracer trace.Tracer + propagator propagation.TextMapPropagator +} + +// newOtelTracer creates an OTel TracerProvider exporting to cfg.CollectorEndpoint via +// OTLP HTTP, registers it (and a composite W3C trace-context/baggage/B3 propagator) as +// the OTel globals, and returns the resulting Tracer alongside its ShutdownFunc. +func newOtelTracer(name string, cfg *config.OtelConfig) (Tracer, ShutdownFunc, error) { + ctx := context.Background() + + // Validate the endpoint has a host before handing it to otlptracehttp: WithEndpointURL + // silently falls back to an empty host on a parse error or an empty/host-less string, + // which would construct an exporter that can never successfully connect. + endpointURL, err := url.Parse(cfg.CollectorEndpoint) + if err != nil { + return nil, nil, err + } + if endpointURL.Host == "" { + return nil, nil, fmt.Errorf("invalid CollectorEndpoint %q: missing host", cfg.CollectorEndpoint) + } + + exporter, err := otlptracehttp.New(ctx, otlptracehttp.WithEndpointURL(cfg.CollectorEndpoint)) + if err != nil { + return nil, nil, err + } + + ratio := cfg.SamplingRatio + if ratio <= 0 { + ratio = 1 + } + + res := resource.NewSchemaless(attribute.String("service.name", name)) + + tp := sdktrace.NewTracerProvider( + sdktrace.WithBatcher(exporter), + sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(ratio))), + sdktrace.WithResource(res), + ) + + // Register both W3C TraceContext and B3 extractors so the router can join traces from + // callers using either propagation format. B3 is Istio's default. + propagator := propagation.NewCompositeTextMapPropagator( + propagation.TraceContext{}, propagation.Baggage{}, b3.New(), + ) + + otel.SetTracerProvider(tp) + otel.SetTextMapPropagator(propagator) + + t := &OtelTracer{ + tracer: tp.Tracer(name), + propagator: propagator, + } + + return t, tp.Shutdown, nil +} + +// IsEnabled satisfies the Tracer interface, always returning true +func (*OtelTracer) IsEnabled() bool { + return true +} + +// StartSpanFromRequestHeader extracts a remote span context from the request header +// (via the W3C traceparent/tracestate or B3 headers) and starts a child span from it. +func (t *OtelTracer) StartSpanFromRequestHeader( + ctx context.Context, + opName string, + header http.Header, +) (trace.Span, context.Context) { + ctx = t.propagator.Extract(ctx, propagation.HeaderCarrier(header)) + ctx, span := t.tracer.Start(ctx, opName) + return span, ctx +} + +// StartSpanFromContext starts a new / child span associated with the given context. +func (t *OtelTracer) StartSpanFromContext( + ctx context.Context, + opName string, +) (trace.Span, context.Context) { + ctx, span := t.tracer.Start(ctx, opName) + return span, ctx +} diff --git a/engines/router/missionctl/instrumentation/tracing/otel_test.go b/engines/router/missionctl/instrumentation/tracing/otel_test.go new file mode 100644 index 000000000..d0a7b86df --- /dev/null +++ b/engines/router/missionctl/instrumentation/tracing/otel_test.go @@ -0,0 +1,116 @@ +package tracing + +import ( + "context" + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/caraml-dev/turing/engines/router/missionctl/config" +) + +func TestNewOtelTracer_IsEnabled(t *testing.T) { + tr, shutdown, err := newOtelTracer("test", &config.OtelConfig{ + Enabled: true, + CollectorEndpoint: "http://localhost:4318", + }) + require.NoError(t, err) + defer func() { _ = shutdown(context.Background()) }() + + assert.Equal(t, true, tr.IsEnabled()) +} + +func TestNewOtelTracer(t *testing.T) { + tr, shutdown, err := newOtelTracer("test", &config.OtelConfig{ + Enabled: true, + CollectorEndpoint: "http://localhost:4318", + SamplingRatio: 0.5, + }) + require.NoError(t, err) + require.NotNil(t, tr) + require.NotNil(t, shutdown) + + defer func() { _ = shutdown(context.Background()) }() +} + +func TestNewOtelTracer_HTTPS(t *testing.T) { + tr, shutdown, err := newOtelTracer("test", &config.OtelConfig{ + Enabled: true, + CollectorEndpoint: "https://localhost:4318", + SamplingRatio: 0.5, + }) + require.NoError(t, err) + defer func() { _ = shutdown(context.Background()) }() + + span, ctx := tr.StartSpanFromContext(context.Background(), "test-op") + assert.NotNil(t, span) + assert.NotNil(t, ctx) + span.End() +} + +func TestOtelTracer_StartSpanFromContext(t *testing.T) { + tr, shutdown, err := newOtelTracer("test", &config.OtelConfig{ + Enabled: true, + CollectorEndpoint: "http://localhost:4318", + }) + require.NoError(t, err) + defer func() { _ = shutdown(context.Background()) }() + + span, ctx := tr.StartSpanFromContext(context.Background(), "test-op") + assert.NotNil(t, span) + assert.NotNil(t, ctx) + span.End() +} + +func TestOtelTracer_StartSpanFromRequestHeader(t *testing.T) { + tr, shutdown, err := newOtelTracer("test", &config.OtelConfig{ + Enabled: true, + CollectorEndpoint: "http://localhost:4318", + }) + require.NoError(t, err) + defer func() { _ = shutdown(context.Background()) }() + + header := http.Header{} + header.Set("traceparent", "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01") + + span, ctx := tr.StartSpanFromRequestHeader(context.Background(), "test-op", header) + assert.NotNil(t, span) + assert.NotNil(t, ctx) + assert.Equal(t, "4bf92f3577b34da6a3ce929d0e0e4736", span.SpanContext().TraceID().String()) + span.End() +} + +// TestOtelTracer_StartSpanFromRequestHeader_B3 confirms that inbound requests carrying B3 +// trace-context headers (Istio/Knative's default propagation format) are joined into the +// same trace, rather than silently producing a disconnected root span. +func TestOtelTracer_StartSpanFromRequestHeader_B3(t *testing.T) { + tr, shutdown, err := newOtelTracer("test", &config.OtelConfig{ + Enabled: true, + CollectorEndpoint: "http://localhost:4318", + }) + require.NoError(t, err) + defer func() { _ = shutdown(context.Background()) }() + + header := http.Header{} + header.Set("X-B3-Traceid", "4bf92f3577b34da6a3ce929d0e0e4736") + header.Set("X-B3-Spanid", "00f067aa0ba902b7") + header.Set("X-B3-Sampled", "1") + + span, ctx := tr.StartSpanFromRequestHeader(context.Background(), "test-op", header) + assert.NotNil(t, span) + assert.NotNil(t, ctx) + assert.Equal(t, "4bf92f3577b34da6a3ce929d0e0e4736", span.SpanContext().TraceID().String()) + assert.True(t, span.SpanContext().IsSampled()) + span.End() +} + +func TestNewOtelTracer_MissingHost(t *testing.T) { + _, _, err := newOtelTracer("test", &config.OtelConfig{ + Enabled: true, + CollectorEndpoint: "", + }) + require.Error(t, err) + assert.Contains(t, err.Error(), "missing host") +} diff --git a/engines/router/missionctl/instrumentation/tracing/tracing.go b/engines/router/missionctl/instrumentation/tracing/tracing.go index 1fb41212b..1a407f377 100644 --- a/engines/router/missionctl/instrumentation/tracing/tracing.go +++ b/engines/router/missionctl/instrumentation/tracing/tracing.go @@ -2,74 +2,96 @@ package tracing import ( "context" - "io" + "errors" "net/http" - "github.com/opentracing/opentracing-go" + "go.opentelemetry.io/otel/trace" "github.com/caraml-dev/turing/engines/router/missionctl/config" ) -// Tracer represents a generic tracer that supports initialization of a global -// tracing client and creation of opentracing spans +// ShutdownFunc flushes and shuts down the tracer provider(s) created by InitGlobalTracer. +type ShutdownFunc func(context.Context) error + +// Tracer represents a generic tracer that supports creation of OpenTelemetry spans. +// Concrete tracers are constructed via their own typed newXTracer function (see +// newOtelTracer, newJaegerTracer, newMultiTracer) rather than through this interface, +// since different backends take different config types. type Tracer interface { - InitGlobalTracer(string, *config.JaegerConfig) (io.Closer, error) IsEnabled() bool StartSpanFromRequestHeader( context.Context, string, http.Header, - ) (opentracing.Span, context.Context) - StartSpanFromContext(context.Context, string) (opentracing.Span, context.Context) + ) (trace.Span, context.Context) + StartSpanFromContext(context.Context, string) (trace.Span, context.Context) } -// baseTracer partially implements the Tracer interface and can be used by all tracers -// to support creation of opentracing spans -type baseTracer struct { -} +// globalTracer is initialised to a Nop tracer, calling InitGlobalTracer will reset this +var globalTracer = newNopTracer() + +// InitGlobalTracer initialises whichever of jaegerCfg/otelCfg are enabled, and sets the +// global tracer to: the Nop tracer if neither is enabled, that single backend's tracer +// if exactly one is enabled, or a MultiTracer fanning out to both if both are enabled. +// The returned ShutdownFunc is always non-nil and safe to call, even when a non-nil +// error is also returned, so callers can unconditionally defer it. +func InitGlobalTracer( + name string, + jaegerCfg *config.JaegerConfig, //nolint:staticcheck + otelCfg *config.OtelConfig, +) (ShutdownFunc, error) { + var tracers []Tracer + var shutdowns []ShutdownFunc -// StartSpanFromRequestHeader attempts to extract span info from the request header and creates a -// new / child span accordingly, which is associated to the given context.Context object. -func (t *baseTracer) StartSpanFromRequestHeader( - ctx context.Context, - opName string, - header http.Header, -) (opentracing.Span, context.Context) { - tr := opentracing.GlobalTracer() - spanCtx, _ := tr.Extract( - opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(header)) - var sp opentracing.Span - if spanCtx != nil { - // Start child span - sp = opentracing.StartSpan(opName, opentracing.ChildOf(spanCtx)) - if sp != nil { - // A (new / child) span has been created, add it to the context - ctx = opentracing.ContextWithSpan(ctx, sp) + // NOTE: order matters here. Otel is appended before Jaeger so that, when both are + // enabled, tracers[0] (and thus spans[0] in the resulting multiSpan) is always the + // Otel tracer/span. multiSpan's SpanContext()/IsRecording()/TracerProvider() delegate + // to spans[0] as the composite's "primary" identity (see multi.go's multiSpan doc + // comment) -- reordering these two blocks would silently flip which backend that + // primary identity comes from, so don't reorder casually. + if otelCfg != nil && otelCfg.Enabled { + t, shutdown, err := newOtelTracer(name, otelCfg) + if err != nil { + return aggregateShutdown(shutdowns), err } + tracers = append(tracers, t) + shutdowns = append(shutdowns, shutdown) } - return sp, ctx -} -// StartSpanFromContext attempts to extract span info from the given context.Context and creates -// a new / child span accordingly, which is associated to the same context object. -func (t *baseTracer) StartSpanFromContext( - ctx context.Context, - opName string, -) (opentracing.Span, context.Context) { - return opentracing.StartSpanFromContext(ctx, opName) -} + // Must stay after the Otel block above -- see the ordering note there. + if jaegerCfg != nil && jaegerCfg.Enabled { + t, shutdown, err := newJaegerTracer(name, jaegerCfg) + if err != nil { + return aggregateShutdown(shutdowns), err + } + tracers = append(tracers, t) + shutdowns = append(shutdowns, shutdown) + } -// globalTracer is initialised to a Nop tracer, calling InitGlobalTracer will reset this -var globalTracer = newNopTracer() + switch len(tracers) { + case 0: + globalTracer = newNopTracer() + case 1: + globalTracer = tracers[0] + default: + globalTracer = newMultiTracer(tracers) + } -// InitGlobalTracer creates a new Jaeger tracer, and sets it as global tracer. -func InitGlobalTracer(name string, jaegerCfg *config.JaegerConfig) (io.Closer, error) { - // If jaeger config has been set and the tracing enabled, initialise the JaegerTracer - if jaegerCfg != nil && jaegerCfg.Enabled { - globalTracer = newJaegerTracer() + return aggregateShutdown(shutdowns), nil +} + +// aggregateShutdown returns a ShutdownFunc that always attempts every shutdown func +// in shutdowns (even if an earlier one errors), combining any errors. +func aggregateShutdown(shutdowns []ShutdownFunc) ShutdownFunc { + return func(ctx context.Context) error { + var errs []error + for _, shutdown := range shutdowns { + if err := shutdown(ctx); err != nil { + errs = append(errs, err) + } + } + return errors.Join(errs...) } - // Initialise the tracer - return globalTracer.InitGlobalTracer(name, jaegerCfg) } // Glob returns the global tracer diff --git a/engines/router/missionctl/instrumentation/tracing/tracing_test.go b/engines/router/missionctl/instrumentation/tracing/tracing_test.go index 68331e846..bc17f57bc 100644 --- a/engines/router/missionctl/instrumentation/tracing/tracing_test.go +++ b/engines/router/missionctl/instrumentation/tracing/tracing_test.go @@ -1,62 +1,104 @@ package tracing import ( + "context" "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/caraml-dev/turing/engines/router/missionctl/config" ) func TestGetGlob(t *testing.T) { - // Save globalTracer in a temp var and reset after the test tempTracer := globalTracer - defer func() { - globalTracer = tempTracer - }() + defer func() { globalTracer = tempTracer }() - // Test globalTracer = &NopTracer{} assert.Equal(t, globalTracer, Glob()) } func TestSetGlob(t *testing.T) { - // Save globalTracer in a temp var and reset after the test tempTracer := globalTracer - defer func() { - globalTracer = tempTracer - }() + defer func() { globalTracer = tempTracer }() - // Test tr := &NopTracer{} SetGlob(tr) assert.Equal(t, tr, globalTracer) } -func TestInitGlobalTracerNop(t *testing.T) { - // Save globalTracer in a temp var and reset after the test +func TestInitGlobalTracer_Nop(t *testing.T) { tempTracer := globalTracer - defer func() { - globalTracer = tempTracer - }() + defer func() { globalTracer = tempTracer }() - _, err := InitGlobalTracer("test", &config.JaegerConfig{}) + _, err := InitGlobalTracer("test", &config.JaegerConfig{}, &config.OtelConfig{}) //nolint:staticcheck assert.NoError(t, err) assert.Equal(t, false, globalTracer.IsEnabled()) } -func TestInitGlobalTracerJaeger(t *testing.T) { - // Save globalTracer in a temp var and reset after the test +func TestInitGlobalTracer_OtelOnly(t *testing.T) { tempTracer := globalTracer - defer func() { - globalTracer = tempTracer - }() + defer func() { globalTracer = tempTracer }() - _, err := InitGlobalTracer("test", &config.JaegerConfig{ + shutdown, err := InitGlobalTracer("test", &config.JaegerConfig{}, &config.OtelConfig{ //nolint:staticcheck Enabled: true, - ReporterAgentHost: "localhost", - ReporterAgentPort: 1000, + CollectorEndpoint: "http://localhost:4318", }) - assert.NoError(t, err) + require.NoError(t, err) + assert.Equal(t, true, globalTracer.IsEnabled()) + assert.IsType(t, &OtelTracer{}, globalTracer) + assert.NoError(t, shutdown(context.Background())) +} + +// TestInitGlobalTracer_JaegerOnly relies on the classic Jaeger client's UDP agent +// reporter not dialling eagerly -- InitGlobalTracer succeeds even with no agent +// listening at the configured host:port, exactly like the OTel exporter today (see +// TestNewOtelTracer in otel_test.go). +func TestInitGlobalTracer_JaegerOnly(t *testing.T) { + tempTracer := globalTracer + defer func() { globalTracer = tempTracer }() + + shutdown, err := InitGlobalTracer("test", &config.JaegerConfig{ //nolint:staticcheck + Enabled: true, + ReporterAgentHost: "localhost", + ReporterAgentPort: 6831, + }, &config.OtelConfig{}) + require.NoError(t, err) + assert.Equal(t, true, globalTracer.IsEnabled()) + assert.IsType(t, &JaegerTracer{}, globalTracer) + assert.NoError(t, shutdown(context.Background())) +} + +func TestInitGlobalTracer_Multi(t *testing.T) { + tempTracer := globalTracer + defer func() { globalTracer = tempTracer }() + + shutdown, err := InitGlobalTracer("test", + &config.JaegerConfig{ //nolint:staticcheck + Enabled: true, + ReporterAgentHost: "localhost", + ReporterAgentPort: 6831, + }, + &config.OtelConfig{ + Enabled: true, + CollectorEndpoint: "http://localhost:4318", + }, + ) + require.NoError(t, err) assert.Equal(t, true, globalTracer.IsEnabled()) + assert.IsType(t, &MultiTracer{}, globalTracer) + assert.NoError(t, shutdown(context.Background())) +} + +func TestInitGlobalTracer_OtelError_ReturnsNonNilShutdown(t *testing.T) { + tempTracer := globalTracer + defer func() { globalTracer = tempTracer }() + + shutdown, err := InitGlobalTracer("test", &config.JaegerConfig{}, &config.OtelConfig{ //nolint:staticcheck + Enabled: true, + CollectorEndpoint: "", + }) + assert.Error(t, err) + require.NotNil(t, shutdown) + assert.NoError(t, shutdown(context.Background())) } diff --git a/engines/router/missionctl/internal/testutils/validation.go b/engines/router/missionctl/internal/testutils/validation.go index 190cfa09c..265ee06a6 100644 --- a/engines/router/missionctl/internal/testutils/validation.go +++ b/engines/router/missionctl/internal/testutils/validation.go @@ -13,7 +13,7 @@ import ( // If the object types have unexported fields, a custom marshaler is required to be defined. func CompareObjects(actual interface{}, expected interface{}) error { allowUnexportedOn := actual - if reflect.TypeOf(allowUnexportedOn).Kind() == reflect.Ptr { + if reflect.TypeOf(allowUnexportedOn).Kind() == reflect.Pointer { allowUnexportedOn = reflect.ValueOf(actual).Elem().Interface() } if !cmp.Equal(actual, expected, cmp.AllowUnexported(allowUnexportedOn)) { diff --git a/engines/router/missionctl/server/application.go b/engines/router/missionctl/server/application.go index 11d773027..ab5497460 100644 --- a/engines/router/missionctl/server/application.go +++ b/engines/router/missionctl/server/application.go @@ -1,8 +1,8 @@ package server import ( + "context" "fmt" - "io" "net" "net/http" @@ -14,6 +14,7 @@ import ( "github.com/caraml-dev/turing/engines/router/missionctl/config" "github.com/caraml-dev/turing/engines/router/missionctl/errors" "github.com/caraml-dev/turing/engines/router/missionctl/instrumentation/metrics" + "github.com/caraml-dev/turing/engines/router/missionctl/instrumentation/profiling" "github.com/caraml-dev/turing/engines/router/missionctl/instrumentation/tracing" "github.com/caraml-dev/turing/engines/router/missionctl/log" "github.com/caraml-dev/turing/engines/router/missionctl/log/resultlog" @@ -128,26 +129,34 @@ func Run() { } } -// initInstrumentation initializes the metrics collector and tracing client +// initInstrumentation initializes the metrics collector, tracing client and profiler func initInstrumentation(cfg *config.Config) func() { - var tracingCloser io.Closer - var err error - // Init metrics collector - err = metrics.InitMetricsCollector(cfg.AppConfig.CustomMetrics) - if err != nil { + if err := metrics.InitMetricsCollector(cfg.AppConfig.CustomMetrics); err != nil { log.Glob().Fatalf("Failed initializing Metrics Collector: %v", err) } // Init tracing client - tracingCloser, err = tracing.InitGlobalTracer(cfg.AppConfig.Name, cfg.AppConfig.Jaeger) + tracingShutdown, err := tracing.InitGlobalTracer(cfg.AppConfig.Name, cfg.AppConfig.Jaeger, cfg.AppConfig.Otel) if err != nil { log.Glob().Fatalf("Failed initializing Tracer: %v", err) } + + // Init profiler + profiler, err := profiling.Start(cfg.AppConfig.Name, cfg.AppConfig.Pyroscope) + if err != nil { + log.Glob().Fatalf("Failed initializing Profiler: %v", err) + } + // Return closer function return func() { - if err := tracingCloser.Close(); err != nil { - panic(err) + if err := tracingShutdown(context.Background()); err != nil { + log.Glob().Errorf("Failed shutting down tracer: %v", err) + } + if profiler != nil { + if err := profiler.Stop(); err != nil { + log.Glob().Errorf("Failed stopping profiler: %v", err) + } } } } diff --git a/engines/router/missionctl/server/http/handlers/batch_http_handler.go b/engines/router/missionctl/server/http/handlers/batch_http_handler.go index 6e2e3ddd5..f6e56d1ee 100644 --- a/engines/router/missionctl/server/http/handlers/batch_http_handler.go +++ b/engines/router/missionctl/server/http/handlers/batch_http_handler.go @@ -8,7 +8,7 @@ import ( "sync" fiberProtocol "github.com/gojek/fiber/protocol" - "github.com/opentracing/opentracing-go" + "go.opentelemetry.io/otel/trace" "github.com/caraml-dev/turing/engines/router/missionctl/instrumentation" @@ -69,10 +69,10 @@ func (h *batchHTTPHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) ctxLogger.Debugf("Received batch request for %v", turingReqID) if tracing.Glob().IsEnabled() { - var sp opentracing.Span + var sp trace.Span ctx, sp = h.enableTracingSpan(ctx, req, batchHTTPHandlerID) if sp != nil { - defer sp.Finish() + defer sp.End() } } diff --git a/engines/router/missionctl/server/http/handlers/http_handler.go b/engines/router/missionctl/server/http/handlers/http_handler.go index e3adb6861..ba245390e 100644 --- a/engines/router/missionctl/server/http/handlers/http_handler.go +++ b/engines/router/missionctl/server/http/handlers/http_handler.go @@ -8,7 +8,7 @@ import ( "time" fiberProtocol "github.com/gojek/fiber/protocol" - "github.com/opentracing/opentracing-go" + "go.opentelemetry.io/otel/trace" "go.uber.org/zap" "github.com/caraml-dev/turing/engines/router/missionctl/instrumentation" @@ -56,8 +56,8 @@ func (h *httpHandler) error( // enableTracingSpan associates span to context, if applicable func (h *httpHandler) enableTracingSpan(ctx context.Context, req *http.Request, - httpHandlerID string) (context.Context, opentracing.Span) { - var sp opentracing.Span + httpHandlerID string) (context.Context, trace.Span) { + var sp trace.Span sp, ctx = tracing.Glob().StartSpanFromRequestHeader(ctx, httpHandlerID, req.Header) return ctx, sp } @@ -116,7 +116,7 @@ func (h *httpHandler) getPrediction( if expResp != nil { var expErr *errors.TuringError if expResp.Error != "" { - expErr = errors.NewTuringError(fmt.Errorf(expResp.Error), fiberProtocol.HTTP) + expErr = errors.NewTuringError(fmt.Errorf("%s", expResp.Error), fiberProtocol.HTTP) } if expResp.Configuration != nil || expErr != nil { h.rl.SendResponseToLogChannel(ctx, respCh, resultlog.ResultLogKeys.Experiment, expResp, expErr) @@ -172,10 +172,10 @@ func (h *httpHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { req.Header.Set(constant.TuringReqIDHeaderKey, turingReqID) if tracing.Glob().IsEnabled() { - var sp opentracing.Span + var sp trace.Span ctx, sp = h.enableTracingSpan(ctx, req, httpHandlerID) if sp != nil { - defer sp.Finish() + defer sp.End() } } diff --git a/engines/router/missionctl/server/upi/server.go b/engines/router/missionctl/server/upi/server.go index 0bed03076..5185d29a8 100644 --- a/engines/router/missionctl/server/upi/server.go +++ b/engines/router/missionctl/server/upi/server.go @@ -7,7 +7,7 @@ import ( "os/signal" "syscall" - "github.com/opentracing/opentracing-go" + "go.opentelemetry.io/otel/trace" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" @@ -117,10 +117,10 @@ func (us *Server) PredictValues(ctx context.Context, req *upiv1.PredictValuesReq md.Append(constant.TuringReqIDHeaderKey, turingReqID) if tracing.Glob().IsEnabled() { - var sp opentracing.Span + var sp trace.Span sp, ctx = tracing.Glob().StartSpanFromContext(ctx, tracingComponentID) if sp != nil { - defer sp.Finish() + defer sp.End() } } diff --git a/sdk/.coveragerc b/sdk/.coveragerc index 1ce887926..bbdd3f52e 100644 --- a/sdk/.coveragerc +++ b/sdk/.coveragerc @@ -1,3 +1,3 @@ [run] omit = - turing/generated/* \ No newline at end of file + turing/generated/* diff --git a/sdk/turing/generated/model/router_version_log_config.py b/sdk/turing/generated/model/router_version_log_config.py index c6814c880..85b78afc6 100644 --- a/sdk/turing/generated/model/router_version_log_config.py +++ b/sdk/turing/generated/model/router_version_log_config.py @@ -87,6 +87,8 @@ def openapi_types(): 'custom_metrics_enabled': (bool,), # noqa: E501 'fiber_debug_log_enabled': (bool,), # noqa: E501 'jaeger_enabled': (bool,), # noqa: E501 + 'otel_enabled': (bool,), # noqa: E501 + 'pyroscope_enabled': (bool,), # noqa: E501 'result_logger_type': (ResultLoggerType,), # noqa: E501 'bigquery_config': (BigQueryConfig,), # noqa: E501 'kafka_config': (KafkaConfig,), # noqa: E501 @@ -102,6 +104,8 @@ def discriminator(): 'custom_metrics_enabled': 'custom_metrics_enabled', # noqa: E501 'fiber_debug_log_enabled': 'fiber_debug_log_enabled', # noqa: E501 'jaeger_enabled': 'jaeger_enabled', # noqa: E501 + 'otel_enabled': 'otel_enabled', # noqa: E501 + 'pyroscope_enabled': 'pyroscope_enabled', # noqa: E501 'result_logger_type': 'result_logger_type', # noqa: E501 'bigquery_config': 'bigquery_config', # noqa: E501 'kafka_config': 'kafka_config', # noqa: E501 @@ -156,7 +160,9 @@ def __init__(self, *args, **kwargs): # noqa: E501 log_level (LogLevel): [optional] # noqa: E501 custom_metrics_enabled (bool): [optional] # noqa: E501 fiber_debug_log_enabled (bool): [optional] # noqa: E501 - jaeger_enabled (bool): [optional] # noqa: E501 + jaeger_enabled (bool): Deprecated: use otel_enabled instead. Will be removed in a future release.. [optional] # noqa: E501 + otel_enabled (bool): [optional] # noqa: E501 + pyroscope_enabled (bool): [optional] # noqa: E501 result_logger_type (ResultLoggerType): [optional] # noqa: E501 bigquery_config (BigQueryConfig): [optional] # noqa: E501 kafka_config (KafkaConfig): [optional] # noqa: E501