mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2024-11-25 08:59:31 -05:00
Revert "Open telemetry integration (#3972)"
This reverts commit c738542201
.
This commit is contained in:
parent
690b63fc74
commit
2e2a044493
19 changed files with 10 additions and 1281 deletions
|
@ -57,10 +57,6 @@ jobs:
|
||||||
MINIO_DOMAIN: minio
|
MINIO_DOMAIN: minio
|
||||||
MINIO_ROOT_USER: 123456
|
MINIO_ROOT_USER: 123456
|
||||||
MINIO_ROOT_PASSWORD: 12345678
|
MINIO_ROOT_PASSWORD: 12345678
|
||||||
jaeger:
|
|
||||||
image: docker.io/jaegertracing/all-in-one:1.58
|
|
||||||
env:
|
|
||||||
COLLECTOR_OTLP_ENABLED: true
|
|
||||||
steps:
|
steps:
|
||||||
- uses: https://code.forgejo.org/actions/checkout@v3
|
- uses: https://code.forgejo.org/actions/checkout@v3
|
||||||
- uses: https://code.forgejo.org/actions/setup-go@v4
|
- uses: https://code.forgejo.org/actions/setup-go@v4
|
||||||
|
@ -95,7 +91,6 @@ jobs:
|
||||||
RACE_ENABLED: 'true'
|
RACE_ENABLED: 'true'
|
||||||
TAGS: bindata
|
TAGS: bindata
|
||||||
TEST_ELASTICSEARCH_URL: http://elasticsearch:9200
|
TEST_ELASTICSEARCH_URL: http://elasticsearch:9200
|
||||||
TEST_OTEL_URL: http://jaeger:4317
|
|
||||||
test-remote-cacher:
|
test-remote-cacher:
|
||||||
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
if: ${{ !startsWith(vars.ROLE, 'forgejo-') }}
|
||||||
runs-on: docker
|
runs-on: docker
|
||||||
|
|
|
@ -17,7 +17,6 @@ linters:
|
||||||
- nakedret
|
- nakedret
|
||||||
- nolintlint
|
- nolintlint
|
||||||
- revive
|
- revive
|
||||||
- spancheck
|
|
||||||
- staticcheck
|
- staticcheck
|
||||||
- stylecheck
|
- stylecheck
|
||||||
- tenv
|
- tenv
|
||||||
|
|
79
assets/go-licenses.json
generated
79
assets/go-licenses.json
generated
File diff suppressed because one or more lines are too long
|
@ -2606,70 +2606,6 @@ LEVEL = Info
|
||||||
;; Enable RPM re-signing by default. (It will overwrite the old signature ,using v4 format, not compatible with CentOS 6 or older)
|
;; Enable RPM re-signing by default. (It will overwrite the old signature ,using v4 format, not compatible with CentOS 6 or older)
|
||||||
;DEFAULT_RPM_SIGN_ENABLED = false
|
;DEFAULT_RPM_SIGN_ENABLED = false
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;[opentelemetry]
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
|
|
||||||
;; https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#general-sdk-configuration&ia=web
|
|
||||||
;; Enable the feature, Inverse of OTEL_SDK_DISABLED
|
|
||||||
;ENABLED = false
|
|
||||||
;; Comma separated custom attributes for the application
|
|
||||||
;RESOURCE_ATTRIBUTES =
|
|
||||||
;; Service name for the application
|
|
||||||
;SERVICE_NAME = forgejo
|
|
||||||
;; Set sampler used by trace exporter, accepted values are:
|
|
||||||
;; - `always_off` - never samples spans
|
|
||||||
;; - `always_on` - always samples spans
|
|
||||||
;; - `traceidratio` - samples based on given ratio given in SAMPLER_ARG
|
|
||||||
;; - `parentbased_always_off` - samples based on parent span, never samples spans without parent spans
|
|
||||||
;; - `parentbased_always_on` - samples based on parent span, always samples spans without parent spans
|
|
||||||
;; - `parentbased_traceidratio` - samples based on parent span, samples spans without parent spans on given ratio given in SAMPLER_ARG
|
|
||||||
;TRACES_SAMPLER = parentbased_always_on
|
|
||||||
;; Argument for the sampler, only applies to traceidratio based samplers
|
|
||||||
;; `traceidratio` expects a value between 0-1 based on which it samples (`0` it acts like `always_off`, `1` like `always_on`)
|
|
||||||
;TRACES_SAMPLER_ARG =
|
|
||||||
|
|
||||||
;; https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/#exporter-selection
|
|
||||||
;; Controls the exporter used to send data, set to `none` to fully disable the signal
|
|
||||||
;TRACES_EXPORTER=otlp
|
|
||||||
|
|
||||||
|
|
||||||
;; Active decoders for attributes, available values:
|
|
||||||
;; - `sdk` - adds information about opentelemetry sdk used
|
|
||||||
;; - `process` - adds information about the process
|
|
||||||
;; - `os` - adds information about the OS forgejo is running on
|
|
||||||
;; - `host` - adds information about the host forgejo is running on
|
|
||||||
;; This setting is non-standard and subject to changes!
|
|
||||||
;RESOURCE_DETECTORS = host,process
|
|
||||||
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;;[opentelemetry.exporter.otlp]
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
||||||
;; https://opentelemetry.io/docs/specs/otel/protocol/exporter/#configuration-options
|
|
||||||
|
|
||||||
;; Target URL to which the exporter is going to send spans, metrics, or logs.
|
|
||||||
;ENDPOINT=http://localhost:4318
|
|
||||||
;; The trusted certificate to use when verifying a server’s TLS credentials. Should only be used for a secure connection.
|
|
||||||
;CERTIFICATE=
|
|
||||||
;; Client certificate/chain trust for clients private key to use in mTLS communication in PEM format.
|
|
||||||
;CLIENT_CERTIFICATE=
|
|
||||||
;; Clients private key to use in mTLS communication in PEM format.
|
|
||||||
;CLIENT_KEY=
|
|
||||||
;; Compression key for supported compression types. Supported compression: `gzip`.
|
|
||||||
;COMPRESSION=
|
|
||||||
;; Key-value pairs to be used as headers associated with gRPC or HTTP requests
|
|
||||||
;HEADERS=
|
|
||||||
;; The transport protocol. Options MUST be one of: `grpc`, or `http/protobuf`
|
|
||||||
;PROTOCOL=http/protobuf
|
|
||||||
;; Maximum time the OTLP exporter will wait for each batch export.
|
|
||||||
;TIMEOUT=10s
|
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; default storage for attachments, lfs and avatars
|
;; default storage for attachments, lfs and avatars
|
||||||
|
|
16
go.mod
16
go.mod
|
@ -45,7 +45,6 @@ require (
|
||||||
github.com/go-git/go-billy/v5 v5.5.0
|
github.com/go-git/go-billy/v5 v5.5.0
|
||||||
github.com/go-git/go-git/v5 v5.11.0
|
github.com/go-git/go-git/v5 v5.11.0
|
||||||
github.com/go-ldap/ldap/v3 v3.4.6
|
github.com/go-ldap/ldap/v3 v3.4.6
|
||||||
github.com/go-logr/logr v1.4.2
|
|
||||||
github.com/go-sql-driver/mysql v1.8.1
|
github.com/go-sql-driver/mysql v1.8.1
|
||||||
github.com/go-swagger/go-swagger v0.30.5
|
github.com/go-swagger/go-swagger v0.30.5
|
||||||
github.com/go-testfixtures/testfixtures/v3 v3.12.0
|
github.com/go-testfixtures/testfixtures/v3 v3.12.0
|
||||||
|
@ -87,7 +86,6 @@ require (
|
||||||
github.com/prometheus/client_golang v1.18.0
|
github.com/prometheus/client_golang v1.18.0
|
||||||
github.com/quasoft/websspi v1.1.2
|
github.com/quasoft/websspi v1.1.2
|
||||||
github.com/redis/go-redis/v9 v9.5.2
|
github.com/redis/go-redis/v9 v9.5.2
|
||||||
github.com/riandyrn/otelchi v0.8.0
|
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1
|
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1
|
||||||
github.com/sassoftware/go-rpmutils v0.4.0
|
github.com/sassoftware/go-rpmutils v0.4.0
|
||||||
|
@ -102,10 +100,6 @@ require (
|
||||||
github.com/yohcop/openid-go v1.0.1
|
github.com/yohcop/openid-go v1.0.1
|
||||||
github.com/yuin/goldmark v1.7.4
|
github.com/yuin/goldmark v1.7.4
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
|
||||||
go.opentelemetry.io/otel v1.27.0
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0
|
|
||||||
go.opentelemetry.io/otel/sdk v1.27.0
|
|
||||||
go.uber.org/mock v0.4.0
|
go.uber.org/mock v0.4.0
|
||||||
golang.org/x/crypto v0.25.0
|
golang.org/x/crypto v0.25.0
|
||||||
golang.org/x/image v0.18.0
|
golang.org/x/image v0.18.0
|
||||||
|
@ -165,7 +159,6 @@ require (
|
||||||
github.com/boombuler/barcode v1.0.1 // indirect
|
github.com/boombuler/barcode v1.0.1 // indirect
|
||||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
|
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
|
||||||
github.com/caddyserver/zerossl v0.1.2 // indirect
|
github.com/caddyserver/zerossl v0.1.2 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
|
||||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/cloudflare/circl v1.3.8 // indirect
|
github.com/cloudflare/circl v1.3.8 // indirect
|
||||||
|
@ -189,7 +182,6 @@ require (
|
||||||
github.com/go-faster/errors v0.7.1 // indirect
|
github.com/go-faster/errors v0.7.1 // indirect
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-ini/ini v1.67.0 // indirect
|
github.com/go-ini/ini v1.67.0 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
|
||||||
github.com/go-openapi/analysis v0.22.2 // indirect
|
github.com/go-openapi/analysis v0.22.2 // indirect
|
||||||
github.com/go-openapi/errors v0.21.0 // indirect
|
github.com/go-openapi/errors v0.21.0 // indirect
|
||||||
github.com/go-openapi/inflect v0.19.0 // indirect
|
github.com/go-openapi/inflect v0.19.0 // indirect
|
||||||
|
@ -216,7 +208,6 @@ require (
|
||||||
github.com/gorilla/handlers v1.5.2 // indirect
|
github.com/gorilla/handlers v1.5.2 // indirect
|
||||||
github.com/gorilla/mux v1.8.1 // indirect
|
github.com/gorilla/mux v1.8.1 // indirect
|
||||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
|
|
||||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
|
||||||
|
@ -288,10 +279,8 @@ require (
|
||||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||||
go.etcd.io/bbolt v1.3.9 // indirect
|
go.etcd.io/bbolt v1.3.9 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.13.1 // indirect
|
go.mongodb.org/mongo-driver v1.13.1 // indirect
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 // indirect
|
go.opentelemetry.io/otel v1.26.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.27.0 // indirect
|
go.opentelemetry.io/otel/trace v1.26.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.27.0 // indirect
|
|
||||||
go.opentelemetry.io/proto/otlp v1.2.0 // indirect
|
|
||||||
go.uber.org/atomic v1.11.0 // indirect
|
go.uber.org/atomic v1.11.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
|
@ -299,7 +288,6 @@ require (
|
||||||
golang.org/x/mod v0.19.0 // indirect
|
golang.org/x/mod v0.19.0 // indirect
|
||||||
golang.org/x/sync v0.7.0 // indirect
|
golang.org/x/sync v0.7.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.5.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 // indirect
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||||
|
|
33
go.sum
33
go.sum
|
@ -149,8 +149,6 @@ github.com/caddyserver/certmagic v0.21.0 h1:yDoifClc4hIxhHer3AxUj4buhF+NzRR6torw
|
||||||
github.com/caddyserver/certmagic v0.21.0/go.mod h1:OgUZNXYV/ylYoFJNmoYVR5nntydLNMQISePPgqZTyhc=
|
github.com/caddyserver/certmagic v0.21.0/go.mod h1:OgUZNXYV/ylYoFJNmoYVR5nntydLNMQISePPgqZTyhc=
|
||||||
github.com/caddyserver/zerossl v0.1.2 h1:tlEu1VzWGoqcCpivs9liKAKhfpJWYJkHEMmlxRbVAxE=
|
github.com/caddyserver/zerossl v0.1.2 h1:tlEu1VzWGoqcCpivs9liKAKhfpJWYJkHEMmlxRbVAxE=
|
||||||
github.com/caddyserver/zerossl v0.1.2/go.mod h1:wtiJEHbdvunr40ZzhXlnIkOB8Xj4eKtBKizCcZitJiQ=
|
github.com/caddyserver/zerossl v0.1.2/go.mod h1:wtiJEHbdvunr40ZzhXlnIkOB8Xj4eKtBKizCcZitJiQ=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
|
||||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a h1:MISbI8sU/PSK/ztvmWKFcI7UGb5/HQT7B+i3a2myKgI=
|
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a h1:MISbI8sU/PSK/ztvmWKFcI7UGb5/HQT7B+i3a2myKgI=
|
||||||
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXOlEPAMFPfp014mK1SWq8G8BN8o7/dfYqJrVGn8=
|
github.com/cention-sany/utf7 v0.0.0-20170124080048-26cad61bd60a/go.mod h1:2GxOXOlEPAMFPfp014mK1SWq8G8BN8o7/dfYqJrVGn8=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
|
@ -273,11 +271,6 @@ github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
||||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A=
|
github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc=
|
github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
|
||||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
|
||||||
github.com/go-logr/logr v1.4.2/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-openapi/analysis v0.22.2 h1:ZBmNoP2h5omLKr/srIC9bfqrUGzT6g6gNv03HE9Vpj0=
|
github.com/go-openapi/analysis v0.22.2 h1:ZBmNoP2h5omLKr/srIC9bfqrUGzT6g6gNv03HE9Vpj0=
|
||||||
github.com/go-openapi/analysis v0.22.2/go.mod h1:pDF4UbZsQTo/oNuRfAWWd4dAh4yuYf//LYorPTjrpvo=
|
github.com/go-openapi/analysis v0.22.2/go.mod h1:pDF4UbZsQTo/oNuRfAWWd4dAh4yuYf//LYorPTjrpvo=
|
||||||
github.com/go-openapi/errors v0.21.0 h1:FhChC/duCnfoLj1gZ0BgaBmzhJC2SL/sJr8a2vAobSY=
|
github.com/go-openapi/errors v0.21.0 h1:FhChC/duCnfoLj1gZ0BgaBmzhJC2SL/sJr8a2vAobSY=
|
||||||
|
@ -403,8 +396,6 @@ github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pw
|
||||||
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||||
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
||||||
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
|
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
|
|
||||||
github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
|
github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE=
|
||||||
github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
|
github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk=
|
||||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||||
|
@ -621,8 +612,6 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6O
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/rhysd/actionlint v1.6.27 h1:xxwe8YmveBcC8lydW6GoHMGmB6H/MTqUU60F2p10wjw=
|
github.com/rhysd/actionlint v1.6.27 h1:xxwe8YmveBcC8lydW6GoHMGmB6H/MTqUU60F2p10wjw=
|
||||||
github.com/rhysd/actionlint v1.6.27/go.mod h1:m2nFUjAnOrxCMXuOMz9evYBRCLUsMnKY2IJl/N5umbk=
|
github.com/rhysd/actionlint v1.6.27/go.mod h1:m2nFUjAnOrxCMXuOMz9evYBRCLUsMnKY2IJl/N5umbk=
|
||||||
github.com/riandyrn/otelchi v0.8.0 h1:q60HKpwt1MmGjOWgM7m5gGyXYAY3DfTSdfBdBt6ICV4=
|
|
||||||
github.com/riandyrn/otelchi v0.8.0/go.mod h1:ErTae2TG7lrOtEPFsd5/hYLOHJpkk0NNyMaeTMWxl0U=
|
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
|
@ -762,22 +751,10 @@ go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
|
||||||
go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
|
go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
|
||||||
go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=
|
go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=
|
||||||
go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
|
go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
|
||||||
go.opentelemetry.io/otel v1.27.0 h1:9BZoF3yMK/O1AafMiQTVu0YDj5Ea4hPhxCs7sGva+cg=
|
go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs=
|
||||||
go.opentelemetry.io/otel v1.27.0/go.mod h1:DMpAK8fzYRzs+bi3rS5REupisuqTheUlSZJ1WnZaPAQ=
|
go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0 h1:R9DE4kQ4k+YtfLI2ULwX82VtNQ2J8yZmA7ZIF/D+7Mc=
|
go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.27.0/go.mod h1:OQFyQVrDlbe+R7xrEyDr/2Wr67Ol0hRUgsfA+V5A95s=
|
go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0=
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0 h1:H2JFgRcGiyHg7H7bwcwaQJYrNFqCqrbTQ8K4p1OvDu8=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.22.0/go.mod h1:WfCWp1bGoYK8MeULtI15MmQVczfR+bFkk0DF3h06QmQ=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0 h1:QY7/0NeRPKlzusf40ZE4t1VlMKbqSNT7cJRYzWuja0s=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.27.0/go.mod h1:HVkSiDhTM9BoUJU8qE6j2eSWLLXvi1USXjyd2BXT8PY=
|
|
||||||
go.opentelemetry.io/otel/metric v1.27.0 h1:hvj3vdEKyeCi4YaYfNjv2NUje8FqKqUY8IlF0FxV/ik=
|
|
||||||
go.opentelemetry.io/otel/metric v1.27.0/go.mod h1:mVFgmRlhljgBiuk/MP/oKylr4hs85GZAylncepAX/ak=
|
|
||||||
go.opentelemetry.io/otel/sdk v1.27.0 h1:mlk+/Y1gLPLn84U4tI8d3GNJmGT/eXe3ZuOXN9kTWmI=
|
|
||||||
go.opentelemetry.io/otel/sdk v1.27.0/go.mod h1:Ha9vbLwJE6W86YstIywK2xFfPjbWlCuwPtMkKdz/Y4A=
|
|
||||||
go.opentelemetry.io/otel/trace v1.27.0 h1:IqYb813p7cmbHk0a5y6pD5JPakbVfftRXABGt5/Rscw=
|
|
||||||
go.opentelemetry.io/otel/trace v1.27.0/go.mod h1:6RiD1hkAprV4/q+yd2ln1HG9GoPx39SuvvstaLBl+l4=
|
|
||||||
go.opentelemetry.io/proto/otlp v1.2.0 h1:pVeZGk7nXDC9O2hncA6nHldxEjm6LByfA2aN8IOkz94=
|
|
||||||
go.opentelemetry.io/proto/otlp v1.2.0/go.mod h1:gGpR8txAl5M03pDhMC79G6SdqNV26naRm/KDsgaHD8A=
|
|
||||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
|
@ -925,8 +902,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/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-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw=
|
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU=
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157 h1:Zy9XzmMEflZ/MAaA7vNcoebnRAld7FsPW1EeBB7V0m8=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240528184218-531527333157/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0=
|
||||||
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc=
|
||||||
|
|
|
@ -1,96 +0,0 @@
|
||||||
// Copyright 2024 TheFox0x7. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: EUPL-1.2
|
|
||||||
|
|
||||||
package opentelemetry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
"crypto/x509"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/graceful"
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
|
|
||||||
"github.com/go-logr/logr/funcr"
|
|
||||||
"go.opentelemetry.io/otel"
|
|
||||||
"go.opentelemetry.io/otel/propagation"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Init(ctx context.Context) error {
|
|
||||||
// Redirect otel logger to write to common forgejo log at info
|
|
||||||
logWrap := funcr.New(func(prefix, args string) {
|
|
||||||
log.Info(fmt.Sprint(prefix, args))
|
|
||||||
}, funcr.Options{})
|
|
||||||
otel.SetLogger(logWrap)
|
|
||||||
// Redirect error handling to forgejo log as well
|
|
||||||
otel.SetErrorHandler(otel.ErrorHandlerFunc(func(cause error) {
|
|
||||||
log.Error("internal opentelemetry error was raised: %s", cause)
|
|
||||||
}))
|
|
||||||
var shutdownFuncs []func(context.Context) error
|
|
||||||
shutdownCtx := context.Background()
|
|
||||||
|
|
||||||
otel.SetTextMapPropagator(newPropagator())
|
|
||||||
|
|
||||||
res, err := newResource(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
traceShutdown, err := setupTraceProvider(ctx, res)
|
|
||||||
if err != nil {
|
|
||||||
log.Warn("OpenTelemetry trace setup failed, err=%s", err)
|
|
||||||
} else {
|
|
||||||
shutdownFuncs = append(shutdownFuncs, traceShutdown)
|
|
||||||
}
|
|
||||||
|
|
||||||
graceful.GetManager().RunAtShutdown(ctx, func() {
|
|
||||||
for _, fn := range shutdownFuncs {
|
|
||||||
if err := fn(shutdownCtx); err != nil {
|
|
||||||
log.Warn("exporter shutdown failed, err=%s", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
shutdownFuncs = nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func newPropagator() propagation.TextMapPropagator {
|
|
||||||
return propagation.NewCompositeTextMapPropagator(
|
|
||||||
propagation.TraceContext{},
|
|
||||||
propagation.Baggage{},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func withCertPool(path string, tlsConf *tls.Config) {
|
|
||||||
if path == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
log.Warn("Otel: reading ca cert failed path=%s, err=%s", path, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
cp := x509.NewCertPool()
|
|
||||||
if ok := cp.AppendCertsFromPEM(b); !ok {
|
|
||||||
log.Warn("Otel: no valid PEM certificate found path=%s", path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
tlsConf.RootCAs = cp
|
|
||||||
}
|
|
||||||
|
|
||||||
func withClientCert(nc, nk string, tlsConf *tls.Config) {
|
|
||||||
if nc == "" || nk == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
crt, err := tls.LoadX509KeyPair(nc, nk)
|
|
||||||
if err != nil {
|
|
||||||
log.Warn("Otel: create tls client key pair failed")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
tlsConf.Certificates = append(tlsConf.Certificates, crt)
|
|
||||||
}
|
|
|
@ -1,121 +0,0 @@
|
||||||
// Copyright 2024 TheFox0x7. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: EUPL-1.2
|
|
||||||
|
|
||||||
package opentelemetry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/ed25519"
|
|
||||||
"crypto/rand"
|
|
||||||
"crypto/tls"
|
|
||||||
"crypto/x509"
|
|
||||||
"crypto/x509/pkix"
|
|
||||||
"encoding/pem"
|
|
||||||
"math/big"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/modules/test"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"go.opentelemetry.io/otel"
|
|
||||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
|
||||||
"go.opentelemetry.io/otel/sdk/trace/tracetest"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestNoopDefault(t *testing.T) {
|
|
||||||
inMem := tracetest.NewInMemoryExporter()
|
|
||||||
called := false
|
|
||||||
exp := func(ctx context.Context) (sdktrace.SpanExporter, error) {
|
|
||||||
called = true
|
|
||||||
return inMem, nil
|
|
||||||
}
|
|
||||||
exporter["inmemory"] = exp
|
|
||||||
t.Cleanup(func() {
|
|
||||||
delete(exporter, "inmemory")
|
|
||||||
})
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.Traces, "inmemory")
|
|
||||||
|
|
||||||
ctx := context.Background()
|
|
||||||
require.NoError(t, Init(ctx))
|
|
||||||
tracer := otel.Tracer("test_noop")
|
|
||||||
|
|
||||||
_, span := tracer.Start(ctx, "test span")
|
|
||||||
defer span.End()
|
|
||||||
|
|
||||||
assert.False(t, span.SpanContext().HasTraceID())
|
|
||||||
assert.False(t, span.SpanContext().HasSpanID())
|
|
||||||
assert.False(t, called)
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateTestTLS(t *testing.T, path, host string) *tls.Config {
|
|
||||||
_, priv, err := ed25519.GenerateKey(rand.Reader)
|
|
||||||
require.NoError(t, err, "Failed to generate private key: %v", err)
|
|
||||||
|
|
||||||
keyUsage := x509.KeyUsageDigitalSignature
|
|
||||||
|
|
||||||
notBefore := time.Now()
|
|
||||||
notAfter := notBefore.Add(time.Hour)
|
|
||||||
|
|
||||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
|
||||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
|
||||||
require.NoError(t, err, "Failed to generate serial number: %v", err)
|
|
||||||
|
|
||||||
template := x509.Certificate{
|
|
||||||
SerialNumber: serialNumber,
|
|
||||||
Subject: pkix.Name{
|
|
||||||
Organization: []string{"Forgejo Testing"},
|
|
||||||
},
|
|
||||||
NotBefore: notBefore,
|
|
||||||
NotAfter: notAfter,
|
|
||||||
|
|
||||||
KeyUsage: keyUsage,
|
|
||||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth},
|
|
||||||
BasicConstraintsValid: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
hosts := strings.Split(host, ",")
|
|
||||||
for _, h := range hosts {
|
|
||||||
if ip := net.ParseIP(h); ip != nil {
|
|
||||||
template.IPAddresses = append(template.IPAddresses, ip)
|
|
||||||
} else {
|
|
||||||
template.DNSNames = append(template.DNSNames, h)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, priv.Public(), priv)
|
|
||||||
require.NoError(t, err, "Failed to create certificate: %v", err)
|
|
||||||
|
|
||||||
certOut, err := os.Create(path + "/cert.pem")
|
|
||||||
require.NoError(t, err, "Failed to open cert.pem for writing: %v", err)
|
|
||||||
|
|
||||||
if err := pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes}); err != nil {
|
|
||||||
t.Fatalf("Failed to write data to cert.pem: %v", err)
|
|
||||||
}
|
|
||||||
if err := certOut.Close(); err != nil {
|
|
||||||
t.Fatalf("Error closing cert.pem: %v", err)
|
|
||||||
}
|
|
||||||
keyOut, err := os.OpenFile(path+"/key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
|
|
||||||
require.NoError(t, err, "Failed to open key.pem for writing: %v", err)
|
|
||||||
|
|
||||||
privBytes, err := x509.MarshalPKCS8PrivateKey(priv)
|
|
||||||
require.NoError(t, err, "Unable to marshal private key: %v", err)
|
|
||||||
|
|
||||||
if err := pem.Encode(keyOut, &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes}); err != nil {
|
|
||||||
t.Fatalf("Failed to write data to key.pem: %v", err)
|
|
||||||
}
|
|
||||||
if err := keyOut.Close(); err != nil {
|
|
||||||
t.Fatalf("Error closing key.pem: %v", err)
|
|
||||||
}
|
|
||||||
serverCert, err := tls.LoadX509KeyPair(path+"/cert.pem", path+"/key.pem")
|
|
||||||
require.NoError(t, err, "failed to load the key pair")
|
|
||||||
return &tls.Config{
|
|
||||||
Certificates: []tls.Certificate{serverCert},
|
|
||||||
ClientAuth: tls.RequireAnyClientCert,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,90 +0,0 @@
|
||||||
// Copyright 2024 TheFox0x7. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: EUPL-1.2
|
|
||||||
|
|
||||||
package opentelemetry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
|
|
||||||
"go.opentelemetry.io/otel/attribute"
|
|
||||||
"go.opentelemetry.io/otel/sdk/resource"
|
|
||||||
semconv "go.opentelemetry.io/otel/semconv/v1.25.0"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
decoderTelemetrySdk = "sdk"
|
|
||||||
decoderProcess = "process"
|
|
||||||
decoderOS = "os"
|
|
||||||
decoderHost = "host"
|
|
||||||
)
|
|
||||||
|
|
||||||
func newResource(ctx context.Context) (*resource.Resource, error) {
|
|
||||||
opts := []resource.Option{
|
|
||||||
resource.WithAttributes(parseSettingAttributes(setting.OpenTelemetry.ResourceAttributes)...),
|
|
||||||
}
|
|
||||||
opts = append(opts, parseDecoderOpts()...)
|
|
||||||
opts = append(opts, resource.WithAttributes(
|
|
||||||
semconv.ServiceName(setting.OpenTelemetry.ServiceName),
|
|
||||||
semconv.ServiceVersion(setting.ForgejoVersion),
|
|
||||||
))
|
|
||||||
return resource.New(ctx, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseDecoderOpts() []resource.Option {
|
|
||||||
var opts []resource.Option
|
|
||||||
for _, v := range strings.Split(setting.OpenTelemetry.ResourceDetectors, ",") {
|
|
||||||
switch v {
|
|
||||||
case decoderTelemetrySdk:
|
|
||||||
opts = append(opts, resource.WithTelemetrySDK())
|
|
||||||
case decoderProcess:
|
|
||||||
opts = append(opts, resource.WithProcess())
|
|
||||||
case decoderOS:
|
|
||||||
opts = append(opts, resource.WithOS())
|
|
||||||
case decoderHost:
|
|
||||||
opts = append(opts, resource.WithHost())
|
|
||||||
case "": // Don't warn on empty string
|
|
||||||
default:
|
|
||||||
log.Warn("Ignoring unknown resource decoder option: %s", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return opts
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseSettingAttributes(s string) []attribute.KeyValue {
|
|
||||||
var attrs []attribute.KeyValue
|
|
||||||
rawAttrs := strings.TrimSpace(s)
|
|
||||||
|
|
||||||
if rawAttrs == "" {
|
|
||||||
return attrs
|
|
||||||
}
|
|
||||||
|
|
||||||
pairs := strings.Split(rawAttrs, ",")
|
|
||||||
|
|
||||||
var invalid []string
|
|
||||||
for _, p := range pairs {
|
|
||||||
k, v, found := strings.Cut(p, "=")
|
|
||||||
if !found {
|
|
||||||
invalid = append(invalid, p)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
key := strings.TrimSpace(k)
|
|
||||||
val, err := url.PathUnescape(strings.TrimSpace(v))
|
|
||||||
if err != nil {
|
|
||||||
// Retain original value if decoding fails, otherwise it will be
|
|
||||||
// an empty string.
|
|
||||||
val = v
|
|
||||||
log.Warn("Otel resource attribute decoding error, retaining unescaped value. key=%s, val=%s", key, val)
|
|
||||||
}
|
|
||||||
attrs = append(attrs, attribute.String(key, val))
|
|
||||||
}
|
|
||||||
if len(invalid) > 0 {
|
|
||||||
log.Warn("Partial resource, missing values: %v", invalid)
|
|
||||||
}
|
|
||||||
|
|
||||||
return attrs
|
|
||||||
}
|
|
|
@ -1,73 +0,0 @@
|
||||||
// Copyright 2024 TheFox0x7. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: EUPL-1.2
|
|
||||||
|
|
||||||
package opentelemetry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"slices"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/modules/test"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"go.opentelemetry.io/otel/attribute"
|
|
||||||
"go.opentelemetry.io/otel/sdk/resource"
|
|
||||||
semconv "go.opentelemetry.io/otel/semconv/v1.25.0"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestResourceServiceName(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
resource, err := newResource(ctx)
|
|
||||||
require.NoError(t, err)
|
|
||||||
serviceKeyIdx := slices.IndexFunc(resource.Attributes(), func(v attribute.KeyValue) bool {
|
|
||||||
return v.Key == semconv.ServiceNameKey
|
|
||||||
})
|
|
||||||
require.NotEqual(t, -1, serviceKeyIdx)
|
|
||||||
|
|
||||||
assert.Equal(t, "forgejo", resource.Attributes()[serviceKeyIdx].Value.AsString())
|
|
||||||
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.ServiceName, "non-default value")()
|
|
||||||
resource, err = newResource(ctx)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
serviceKeyIdx = slices.IndexFunc(resource.Attributes(), func(v attribute.KeyValue) bool {
|
|
||||||
return v.Key == semconv.ServiceNameKey
|
|
||||||
})
|
|
||||||
require.NotEqual(t, -1, serviceKeyIdx)
|
|
||||||
|
|
||||||
assert.Equal(t, "non-default value", resource.Attributes()[serviceKeyIdx].Value.AsString())
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestResourceAttributes(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.ResourceDetectors, "foo")()
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.ResourceAttributes, "Test=LABEL,broken,unescape=%XXlabel")()
|
|
||||||
res, err := newResource(ctx)
|
|
||||||
require.NoError(t, err)
|
|
||||||
expected, err := resource.New(ctx, resource.WithAttributes(
|
|
||||||
semconv.ServiceName(setting.OpenTelemetry.ServiceName),
|
|
||||||
semconv.ServiceVersion(setting.ForgejoVersion),
|
|
||||||
attribute.String("Test", "LABEL"),
|
|
||||||
attribute.String("unescape", "%XXlabel"),
|
|
||||||
))
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, expected, res)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDecoderParity(t *testing.T) {
|
|
||||||
ctx := context.Background()
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.ResourceDetectors, "sdk,process,os,host")()
|
|
||||||
exp, err := resource.New(
|
|
||||||
ctx, resource.WithTelemetrySDK(), resource.WithOS(), resource.WithProcess(), resource.WithHost(), resource.WithAttributes(
|
|
||||||
semconv.ServiceName(setting.OpenTelemetry.ServiceName), semconv.ServiceVersion(setting.ForgejoVersion),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
require.NoError(t, err)
|
|
||||||
res2, err := newResource(ctx)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, exp, res2)
|
|
||||||
}
|
|
|
@ -1,98 +0,0 @@
|
||||||
// Copyright 2024 TheFox0x7. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: EUPL-1.2
|
|
||||||
|
|
||||||
package opentelemetry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"crypto/tls"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
|
|
||||||
"go.opentelemetry.io/otel"
|
|
||||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
|
|
||||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
|
|
||||||
"go.opentelemetry.io/otel/sdk/resource"
|
|
||||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
|
||||||
"google.golang.org/grpc/credentials"
|
|
||||||
)
|
|
||||||
|
|
||||||
func newGrpcExporter(ctx context.Context) (sdktrace.SpanExporter, error) {
|
|
||||||
endpoint := setting.OpenTelemetry.OtelTraces.Endpoint
|
|
||||||
|
|
||||||
opts := []otlptracegrpc.Option{}
|
|
||||||
|
|
||||||
tlsConf := &tls.Config{}
|
|
||||||
opts = append(opts, otlptracegrpc.WithEndpoint(endpoint.Host))
|
|
||||||
opts = append(opts, otlptracegrpc.WithTimeout(setting.OpenTelemetry.OtelTraces.Timeout))
|
|
||||||
switch setting.OpenTelemetry.OtelTraces.Endpoint.Scheme {
|
|
||||||
case "http", "unix":
|
|
||||||
opts = append(opts, otlptracegrpc.WithInsecure())
|
|
||||||
}
|
|
||||||
|
|
||||||
if setting.OpenTelemetry.OtelTraces.Compression != "" {
|
|
||||||
opts = append(opts, otlptracegrpc.WithCompressor(setting.OpenTelemetry.OtelTraces.Compression))
|
|
||||||
}
|
|
||||||
withCertPool(setting.OpenTelemetry.OtelTraces.Certificate, tlsConf)
|
|
||||||
withClientCert(setting.OpenTelemetry.OtelTraces.ClientCertificate, setting.OpenTelemetry.OtelTraces.ClientKey, tlsConf)
|
|
||||||
if tlsConf.RootCAs != nil || len(tlsConf.Certificates) > 0 {
|
|
||||||
opts = append(opts, otlptracegrpc.WithTLSCredentials(
|
|
||||||
credentials.NewTLS(tlsConf),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
opts = append(opts, otlptracegrpc.WithHeaders(setting.OpenTelemetry.OtelTraces.Headers))
|
|
||||||
|
|
||||||
return otlptracegrpc.New(ctx, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func newHTTPExporter(ctx context.Context) (sdktrace.SpanExporter, error) {
|
|
||||||
endpoint := setting.OpenTelemetry.OtelTraces.Endpoint
|
|
||||||
opts := []otlptracehttp.Option{}
|
|
||||||
tlsConf := &tls.Config{}
|
|
||||||
opts = append(opts, otlptracehttp.WithEndpoint(endpoint.Host))
|
|
||||||
switch setting.OpenTelemetry.OtelTraces.Endpoint.Scheme {
|
|
||||||
case "http", "unix":
|
|
||||||
opts = append(opts, otlptracehttp.WithInsecure())
|
|
||||||
}
|
|
||||||
switch setting.OpenTelemetry.OtelTraces.Compression {
|
|
||||||
case "gzip":
|
|
||||||
opts = append(opts, otlptracehttp.WithCompression(otlptracehttp.GzipCompression))
|
|
||||||
default:
|
|
||||||
opts = append(opts, otlptracehttp.WithCompression(otlptracehttp.NoCompression))
|
|
||||||
}
|
|
||||||
withCertPool(setting.OpenTelemetry.OtelTraces.Certificate, tlsConf)
|
|
||||||
withClientCert(setting.OpenTelemetry.OtelTraces.ClientCertificate, setting.OpenTelemetry.OtelTraces.ClientKey, tlsConf)
|
|
||||||
if tlsConf.RootCAs != nil || len(tlsConf.Certificates) > 0 {
|
|
||||||
opts = append(opts, otlptracehttp.WithTLSClientConfig(tlsConf))
|
|
||||||
}
|
|
||||||
opts = append(opts, otlptracehttp.WithHeaders(setting.OpenTelemetry.OtelTraces.Headers))
|
|
||||||
|
|
||||||
return otlptracehttp.New(ctx, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
var exporter = map[string]func(context.Context) (sdktrace.SpanExporter, error){
|
|
||||||
"http/protobuf": newHTTPExporter,
|
|
||||||
"grpc": newGrpcExporter,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new and register trace provider from user defined configuration
|
|
||||||
func setupTraceProvider(ctx context.Context, r *resource.Resource) (func(context.Context) error, error) {
|
|
||||||
var shutdown func(context.Context) error
|
|
||||||
switch setting.OpenTelemetry.Traces {
|
|
||||||
case "otlp":
|
|
||||||
traceExporter, err := exporter[setting.OpenTelemetry.OtelTraces.Protocol](ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
traceProvider := sdktrace.NewTracerProvider(
|
|
||||||
sdktrace.WithSampler(setting.OpenTelemetry.Sampler),
|
|
||||||
sdktrace.WithBatcher(traceExporter),
|
|
||||||
sdktrace.WithResource(r),
|
|
||||||
)
|
|
||||||
otel.SetTracerProvider(traceProvider)
|
|
||||||
shutdown = traceProvider.Shutdown
|
|
||||||
default:
|
|
||||||
shutdown = func(ctx context.Context) error { return nil }
|
|
||||||
}
|
|
||||||
return shutdown, nil
|
|
||||||
}
|
|
|
@ -1,114 +0,0 @@
|
||||||
// Copyright 2024 TheFox0x7. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: EUPL-1.2
|
|
||||||
|
|
||||||
package opentelemetry
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/modules/test"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
"go.opentelemetry.io/otel"
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/credentials"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestTraceGrpcExporter(t *testing.T) {
|
|
||||||
grpcMethods := make(chan string)
|
|
||||||
tlsConfig := generateTestTLS(t, os.TempDir(), "localhost,127.0.0.1")
|
|
||||||
assert.NotNil(t, tlsConfig)
|
|
||||||
|
|
||||||
collector := grpc.NewServer(grpc.Creds(credentials.NewTLS(tlsConfig)), grpc.UnknownServiceHandler(func(srv any, stream grpc.ServerStream) error {
|
|
||||||
method, _ := grpc.Method(stream.Context())
|
|
||||||
grpcMethods <- method
|
|
||||||
return nil
|
|
||||||
}))
|
|
||||||
defer collector.GracefulStop()
|
|
||||||
ln, err := net.Listen("tcp", "localhost:0")
|
|
||||||
require.NoError(t, err)
|
|
||||||
defer ln.Close()
|
|
||||||
go collector.Serve(ln)
|
|
||||||
|
|
||||||
traceEndpoint, err := url.Parse("https://" + ln.Addr().String())
|
|
||||||
require.NoError(t, err)
|
|
||||||
config := &setting.OtelExporter{
|
|
||||||
Endpoint: traceEndpoint,
|
|
||||||
Certificate: os.TempDir() + "/cert.pem",
|
|
||||||
ClientCertificate: os.TempDir() + "/cert.pem",
|
|
||||||
ClientKey: os.TempDir() + "/key.pem",
|
|
||||||
Protocol: "grpc",
|
|
||||||
}
|
|
||||||
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.ServiceName, "forgejo-certs")()
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.Enabled, true)()
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.Traces, "otlp")()
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.OtelTraces, config)()
|
|
||||||
ctx := context.Background()
|
|
||||||
require.NoError(t, Init(ctx))
|
|
||||||
|
|
||||||
tracer := otel.Tracer("test_tls")
|
|
||||||
_, span := tracer.Start(ctx, "test span")
|
|
||||||
assert.True(t, span.SpanContext().HasTraceID())
|
|
||||||
assert.True(t, span.SpanContext().HasSpanID())
|
|
||||||
|
|
||||||
span.End()
|
|
||||||
// Give the exporter time to send the span
|
|
||||||
select {
|
|
||||||
case method := <-grpcMethods:
|
|
||||||
assert.Equal(t, "/opentelemetry.proto.collector.trace.v1.TraceService/Export", method)
|
|
||||||
case <-time.After(10 * time.Second):
|
|
||||||
t.Fatal("no grpc call within 10s")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTraceHttpExporter(t *testing.T) {
|
|
||||||
httpCalls := make(chan string)
|
|
||||||
tlsConfig := generateTestTLS(t, os.TempDir(), "localhost,127.0.0.1")
|
|
||||||
assert.NotNil(t, tlsConfig)
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
httpCalls <- r.URL.Path
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
w.Write([]byte(`{"success": true}`))
|
|
||||||
}))
|
|
||||||
server.TLS = tlsConfig
|
|
||||||
|
|
||||||
traceEndpoint, err := url.Parse("http://" + server.Listener.Addr().String())
|
|
||||||
require.NoError(t, err)
|
|
||||||
config := &setting.OtelExporter{
|
|
||||||
Endpoint: traceEndpoint,
|
|
||||||
Certificate: os.TempDir() + "/cert.pem",
|
|
||||||
ClientCertificate: os.TempDir() + "/cert.pem",
|
|
||||||
ClientKey: os.TempDir() + "/key.pem",
|
|
||||||
Protocol: "http/protobuf",
|
|
||||||
}
|
|
||||||
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.ServiceName, "forgejo-certs")()
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.Enabled, true)()
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.Traces, "otlp")()
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.OtelTraces, config)()
|
|
||||||
ctx := context.Background()
|
|
||||||
require.NoError(t, Init(ctx))
|
|
||||||
|
|
||||||
tracer := otel.Tracer("test_tls")
|
|
||||||
_, span := tracer.Start(ctx, "test span")
|
|
||||||
assert.True(t, span.SpanContext().HasTraceID())
|
|
||||||
assert.True(t, span.SpanContext().HasSpanID())
|
|
||||||
|
|
||||||
span.End()
|
|
||||||
select {
|
|
||||||
case path := <-httpCalls:
|
|
||||||
assert.Equal(t, "/v1/traces", path)
|
|
||||||
case <-time.After(10 * time.Second):
|
|
||||||
t.Fatal("no http call within 10s")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,199 +0,0 @@
|
||||||
// Copyright 2024 TheFox0x7. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: EUPL-1.2
|
|
||||||
|
|
||||||
package setting
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/url"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
|
|
||||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
opentelemetrySectionName string = "opentelemetry"
|
|
||||||
exporter string = ".exporter"
|
|
||||||
otlp string = ".otlp"
|
|
||||||
alwaysOn string = "always_on"
|
|
||||||
alwaysOff string = "always_off"
|
|
||||||
traceIDRatio string = "traceidratio"
|
|
||||||
parentBasedAlwaysOn string = "parentbased_always_on"
|
|
||||||
parentBasedAlwaysOff string = "parentbased_always_off"
|
|
||||||
parentBasedTraceIDRatio string = "parentbased_traceidratio"
|
|
||||||
)
|
|
||||||
|
|
||||||
var OpenTelemetry = struct {
|
|
||||||
// Inverse of OTEL_SDK_DISABLE, skips telemetry setup
|
|
||||||
Enabled bool
|
|
||||||
ServiceName string
|
|
||||||
ResourceAttributes string
|
|
||||||
ResourceDetectors string
|
|
||||||
Sampler sdktrace.Sampler
|
|
||||||
Traces string
|
|
||||||
|
|
||||||
OtelTraces *OtelExporter
|
|
||||||
}{
|
|
||||||
ServiceName: "forgejo",
|
|
||||||
Traces: "otel",
|
|
||||||
}
|
|
||||||
|
|
||||||
type OtelExporter struct {
|
|
||||||
Endpoint *url.URL `ini:"ENDPOINT"`
|
|
||||||
Headers map[string]string `ini:"-"`
|
|
||||||
Compression string `ini:"COMPRESSION"`
|
|
||||||
Certificate string `ini:"CERTIFICATE"`
|
|
||||||
ClientKey string `ini:"CLIENT_KEY"`
|
|
||||||
ClientCertificate string `ini:"CLIENT_CERTIFICATE"`
|
|
||||||
Timeout time.Duration `ini:"TIMEOUT"`
|
|
||||||
Protocol string `ini:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func createOtlpExporterConfig(rootCfg ConfigProvider, section string) *OtelExporter {
|
|
||||||
protocols := []string{"http/protobuf", "grpc"}
|
|
||||||
endpoint, _ := url.Parse("http://localhost:4318/")
|
|
||||||
exp := &OtelExporter{
|
|
||||||
Endpoint: endpoint,
|
|
||||||
Timeout: 10 * time.Second,
|
|
||||||
Headers: map[string]string{},
|
|
||||||
Protocol: "http/protobuf",
|
|
||||||
}
|
|
||||||
|
|
||||||
loadSection := func(name string) {
|
|
||||||
otlp := rootCfg.Section(name)
|
|
||||||
if otlp.HasKey("ENDPOINT") {
|
|
||||||
endpoint, err := url.Parse(otlp.Key("ENDPOINT").String())
|
|
||||||
if err != nil {
|
|
||||||
log.Warn("Endpoint parsing failed, section: %s, err %v", name, err)
|
|
||||||
} else {
|
|
||||||
exp.Endpoint = endpoint
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := otlp.MapTo(exp); err != nil {
|
|
||||||
log.Warn("Mapping otlp settings failed, section: %s, err: %v", name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
exp.Protocol = otlp.Key("PROTOCOL").In(exp.Protocol, protocols)
|
|
||||||
|
|
||||||
headers := otlp.Key("HEADERS").String()
|
|
||||||
if headers != "" {
|
|
||||||
for k, v := range _stringToHeader(headers) {
|
|
||||||
exp.Headers[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
loadSection("opentelemetry.exporter.otlp")
|
|
||||||
|
|
||||||
loadSection("opentelemetry.exporter.otlp" + section)
|
|
||||||
|
|
||||||
if len(exp.Certificate) > 0 && !filepath.IsAbs(exp.Certificate) {
|
|
||||||
exp.Certificate = filepath.Join(CustomPath, exp.Certificate)
|
|
||||||
}
|
|
||||||
if len(exp.ClientCertificate) > 0 && !filepath.IsAbs(exp.ClientCertificate) {
|
|
||||||
exp.ClientCertificate = filepath.Join(CustomPath, exp.ClientCertificate)
|
|
||||||
}
|
|
||||||
if len(exp.ClientKey) > 0 && !filepath.IsAbs(exp.ClientKey) {
|
|
||||||
exp.ClientKey = filepath.Join(CustomPath, exp.ClientKey)
|
|
||||||
}
|
|
||||||
|
|
||||||
return exp
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadOpenTelemetryFrom(rootCfg ConfigProvider) {
|
|
||||||
sec := rootCfg.Section(opentelemetrySectionName)
|
|
||||||
OpenTelemetry.Enabled = sec.Key("ENABLED").MustBool(false)
|
|
||||||
if !OpenTelemetry.Enabled {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load resource related settings
|
|
||||||
OpenTelemetry.ServiceName = sec.Key("SERVICE_NAME").MustString("forgejo")
|
|
||||||
OpenTelemetry.ResourceAttributes = sec.Key("RESOURCE_ATTRIBUTES").String()
|
|
||||||
OpenTelemetry.ResourceDetectors = strings.ToLower(sec.Key("RESOURCE_DETECTORS").String())
|
|
||||||
|
|
||||||
// Load tracing related settings
|
|
||||||
samplers := make([]string, 0, len(sampler))
|
|
||||||
for k := range sampler {
|
|
||||||
samplers = append(samplers, k)
|
|
||||||
}
|
|
||||||
|
|
||||||
samplerName := sec.Key("TRACES_SAMPLER").In(parentBasedAlwaysOn, samplers)
|
|
||||||
samplerArg := sec.Key("TRACES_SAMPLER_ARG").MustString("")
|
|
||||||
OpenTelemetry.Sampler = sampler[samplerName](samplerArg)
|
|
||||||
|
|
||||||
switch sec.Key("TRACES_EXPORTER").MustString("otlp") {
|
|
||||||
case "none":
|
|
||||||
OpenTelemetry.Traces = "none"
|
|
||||||
default:
|
|
||||||
OpenTelemetry.Traces = "otlp"
|
|
||||||
OpenTelemetry.OtelTraces = createOtlpExporterConfig(rootCfg, ".traces")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var sampler = map[string]func(arg string) sdktrace.Sampler{
|
|
||||||
alwaysOff: func(_ string) sdktrace.Sampler {
|
|
||||||
return sdktrace.NeverSample()
|
|
||||||
},
|
|
||||||
alwaysOn: func(_ string) sdktrace.Sampler {
|
|
||||||
return sdktrace.AlwaysSample()
|
|
||||||
},
|
|
||||||
traceIDRatio: func(arg string) sdktrace.Sampler {
|
|
||||||
ratio, err := strconv.ParseFloat(arg, 64)
|
|
||||||
if err != nil {
|
|
||||||
ratio = 1
|
|
||||||
}
|
|
||||||
return sdktrace.TraceIDRatioBased(ratio)
|
|
||||||
},
|
|
||||||
parentBasedAlwaysOff: func(_ string) sdktrace.Sampler {
|
|
||||||
return sdktrace.ParentBased(sdktrace.NeverSample())
|
|
||||||
},
|
|
||||||
parentBasedAlwaysOn: func(_ string) sdktrace.Sampler {
|
|
||||||
return sdktrace.ParentBased(sdktrace.AlwaysSample())
|
|
||||||
},
|
|
||||||
parentBasedTraceIDRatio: func(arg string) sdktrace.Sampler {
|
|
||||||
ratio, err := strconv.ParseFloat(arg, 64)
|
|
||||||
if err != nil {
|
|
||||||
ratio = 1
|
|
||||||
}
|
|
||||||
return sdktrace.ParentBased(sdktrace.TraceIDRatioBased(ratio))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Opentelemetry SDK function port
|
|
||||||
|
|
||||||
func _stringToHeader(value string) map[string]string {
|
|
||||||
headersPairs := strings.Split(value, ",")
|
|
||||||
headers := make(map[string]string)
|
|
||||||
|
|
||||||
for _, header := range headersPairs {
|
|
||||||
n, v, found := strings.Cut(header, "=")
|
|
||||||
if !found {
|
|
||||||
log.Warn("Otel header ignored on %q: missing '='", header)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name, err := url.PathUnescape(n)
|
|
||||||
if err != nil {
|
|
||||||
log.Warn("Otel header ignored on %q, invalid header key: %s", header, n)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
trimmedName := strings.TrimSpace(name)
|
|
||||||
value, err := url.PathUnescape(v)
|
|
||||||
if err != nil {
|
|
||||||
log.Warn("Otel header ignored on %q, invalid header value: %s", header, v)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
trimmedValue := strings.TrimSpace(value)
|
|
||||||
|
|
||||||
headers[trimmedName] = trimmedValue
|
|
||||||
}
|
|
||||||
|
|
||||||
return headers
|
|
||||||
}
|
|
||||||
|
|
||||||
func IsOpenTelemetryEnabled() bool {
|
|
||||||
return OpenTelemetry.Enabled
|
|
||||||
}
|
|
|
@ -1,239 +0,0 @@
|
||||||
// Copyright 2024 TheFox0x7. All rights reserved.
|
|
||||||
// SPDX-License-Identifier: EUPL-1.2
|
|
||||||
|
|
||||||
package setting
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/url"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/test"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestExporterLoad(t *testing.T) {
|
|
||||||
globalSetting := `
|
|
||||||
[opentelemetry.exporter.otlp]
|
|
||||||
ENDPOINT=http://example.org:4318/
|
|
||||||
CERTIFICATE=/boo/bar
|
|
||||||
CLIENT_CERTIFICATE=/foo/bar
|
|
||||||
CLIENT_KEY=/bar/bar
|
|
||||||
COMPRESSION=
|
|
||||||
HEADERS=key=val,val=key
|
|
||||||
PROTOCOL=http/protobuf
|
|
||||||
TIMEOUT=20s
|
|
||||||
`
|
|
||||||
endpoint, err := url.Parse("http://example.org:4318/")
|
|
||||||
require.NoError(t, err)
|
|
||||||
expected := &OtelExporter{
|
|
||||||
Endpoint: endpoint,
|
|
||||||
Certificate: "/boo/bar",
|
|
||||||
ClientCertificate: "/foo/bar",
|
|
||||||
ClientKey: "/bar/bar",
|
|
||||||
Headers: map[string]string{
|
|
||||||
"key": "val", "val": "key",
|
|
||||||
},
|
|
||||||
Timeout: 20 * time.Second,
|
|
||||||
Protocol: "http/protobuf",
|
|
||||||
}
|
|
||||||
cfg, err := NewConfigProviderFromData(globalSetting)
|
|
||||||
require.NoError(t, err)
|
|
||||||
exp := createOtlpExporterConfig(cfg, ".traces")
|
|
||||||
assert.Equal(t, expected, exp)
|
|
||||||
localSetting := `
|
|
||||||
[opentelemetry.exporter.otlp.traces]
|
|
||||||
ENDPOINT=http://example.com:4318/
|
|
||||||
CERTIFICATE=/boo
|
|
||||||
CLIENT_CERTIFICATE=/foo
|
|
||||||
CLIENT_KEY=/bar
|
|
||||||
COMPRESSION=gzip
|
|
||||||
HEADERS=key=val2,val1=key
|
|
||||||
PROTOCOL=grpc
|
|
||||||
TIMEOUT=5s
|
|
||||||
`
|
|
||||||
endpoint, err = url.Parse("http://example.com:4318/")
|
|
||||||
require.NoError(t, err)
|
|
||||||
expected = &OtelExporter{
|
|
||||||
Endpoint: endpoint,
|
|
||||||
Certificate: "/boo",
|
|
||||||
ClientCertificate: "/foo",
|
|
||||||
ClientKey: "/bar",
|
|
||||||
Compression: "gzip",
|
|
||||||
Headers: map[string]string{
|
|
||||||
"key": "val2", "val1": "key", "val": "key",
|
|
||||||
},
|
|
||||||
Timeout: 5 * time.Second,
|
|
||||||
Protocol: "grpc",
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg, err = NewConfigProviderFromData(globalSetting + localSetting)
|
|
||||||
require.NoError(t, err)
|
|
||||||
exp = createOtlpExporterConfig(cfg, ".traces")
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, expected, exp)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOpenTelemetryConfiguration(t *testing.T) {
|
|
||||||
defer test.MockProtect(&OpenTelemetry)()
|
|
||||||
iniStr := ``
|
|
||||||
cfg, err := NewConfigProviderFromData(iniStr)
|
|
||||||
require.NoError(t, err)
|
|
||||||
loadOpenTelemetryFrom(cfg)
|
|
||||||
assert.Nil(t, OpenTelemetry.OtelTraces)
|
|
||||||
assert.False(t, IsOpenTelemetryEnabled())
|
|
||||||
|
|
||||||
iniStr = `
|
|
||||||
[opentelemetry]
|
|
||||||
ENABLED=true
|
|
||||||
SERVICE_NAME = test service
|
|
||||||
RESOURCE_ATTRIBUTES = foo=bar
|
|
||||||
TRACES_SAMPLER = always_on
|
|
||||||
|
|
||||||
[opentelemetry.exporter.otlp]
|
|
||||||
ENDPOINT = http://jaeger:4317/
|
|
||||||
TIMEOUT = 30s
|
|
||||||
COMPRESSION = gzip
|
|
||||||
INSECURE = TRUE
|
|
||||||
HEADERS=foo=bar,overwrite=false
|
|
||||||
`
|
|
||||||
cfg, err = NewConfigProviderFromData(iniStr)
|
|
||||||
require.NoError(t, err)
|
|
||||||
loadOpenTelemetryFrom(cfg)
|
|
||||||
|
|
||||||
assert.True(t, IsOpenTelemetryEnabled())
|
|
||||||
assert.Equal(t, "test service", OpenTelemetry.ServiceName)
|
|
||||||
assert.Equal(t, "foo=bar", OpenTelemetry.ResourceAttributes)
|
|
||||||
assert.Equal(t, 30*time.Second, OpenTelemetry.OtelTraces.Timeout)
|
|
||||||
assert.Equal(t, "gzip", OpenTelemetry.OtelTraces.Compression)
|
|
||||||
assert.Equal(t, sdktrace.AlwaysSample(), OpenTelemetry.Sampler)
|
|
||||||
assert.Equal(t, "http://jaeger:4317/", OpenTelemetry.OtelTraces.Endpoint.String())
|
|
||||||
assert.Contains(t, OpenTelemetry.OtelTraces.Headers, "foo")
|
|
||||||
assert.Equal(t, "bar", OpenTelemetry.OtelTraces.Headers["foo"])
|
|
||||||
assert.Contains(t, OpenTelemetry.OtelTraces.Headers, "overwrite")
|
|
||||||
assert.Equal(t, "false", OpenTelemetry.OtelTraces.Headers["overwrite"])
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOpenTelemetryTraceDisable(t *testing.T) {
|
|
||||||
defer test.MockProtect(&OpenTelemetry)()
|
|
||||||
iniStr := ``
|
|
||||||
cfg, err := NewConfigProviderFromData(iniStr)
|
|
||||||
require.NoError(t, err)
|
|
||||||
loadOpenTelemetryFrom(cfg)
|
|
||||||
assert.False(t, OpenTelemetry.Enabled)
|
|
||||||
assert.False(t, IsOpenTelemetryEnabled())
|
|
||||||
|
|
||||||
iniStr = `
|
|
||||||
[opentelemetry]
|
|
||||||
ENABLED=true
|
|
||||||
EXPORTER_OTLP_ENDPOINT =
|
|
||||||
`
|
|
||||||
cfg, err = NewConfigProviderFromData(iniStr)
|
|
||||||
require.NoError(t, err)
|
|
||||||
loadOpenTelemetryFrom(cfg)
|
|
||||||
|
|
||||||
assert.True(t, IsOpenTelemetryEnabled())
|
|
||||||
endpoint, _ := url.Parse("http://localhost:4318/")
|
|
||||||
assert.Equal(t, endpoint, OpenTelemetry.OtelTraces.Endpoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSamplerCombinations(t *testing.T) {
|
|
||||||
defer test.MockProtect(&OpenTelemetry)()
|
|
||||||
type config struct {
|
|
||||||
IniCfg string
|
|
||||||
Expected sdktrace.Sampler
|
|
||||||
}
|
|
||||||
testSamplers := []config{
|
|
||||||
{`[opentelemetry]
|
|
||||||
ENABLED=true
|
|
||||||
TRACES_SAMPLER = always_on
|
|
||||||
TRACES_SAMPLER_ARG = nothing`, sdktrace.AlwaysSample()},
|
|
||||||
{`[opentelemetry]
|
|
||||||
ENABLED=true
|
|
||||||
TRACES_SAMPLER = always_off`, sdktrace.NeverSample()},
|
|
||||||
{`[opentelemetry]
|
|
||||||
ENABLED=true
|
|
||||||
TRACES_SAMPLER = traceidratio
|
|
||||||
TRACES_SAMPLER_ARG = 0.7`, sdktrace.TraceIDRatioBased(0.7)},
|
|
||||||
{`[opentelemetry]
|
|
||||||
ENABLED=true
|
|
||||||
TRACES_SAMPLER = traceidratio
|
|
||||||
TRACES_SAMPLER_ARG = badarg`, sdktrace.TraceIDRatioBased(1)},
|
|
||||||
{`[opentelemetry]
|
|
||||||
ENABLED=true
|
|
||||||
TRACES_SAMPLER = parentbased_always_off`, sdktrace.ParentBased(sdktrace.NeverSample())},
|
|
||||||
{`[opentelemetry]
|
|
||||||
ENABLED=true
|
|
||||||
TRACES_SAMPLER = parentbased_always_of`, sdktrace.ParentBased(sdktrace.AlwaysSample())},
|
|
||||||
{`[opentelemetry]
|
|
||||||
ENABLED=true
|
|
||||||
TRACES_SAMPLER = parentbased_traceidratio
|
|
||||||
TRACES_SAMPLER_ARG = 0.3`, sdktrace.ParentBased(sdktrace.TraceIDRatioBased(0.3))},
|
|
||||||
{`[opentelemetry]
|
|
||||||
ENABLED=true
|
|
||||||
TRACES_SAMPLER = parentbased_traceidratio
|
|
||||||
TRACES_SAMPLER_ARG = badarg`, sdktrace.ParentBased(sdktrace.TraceIDRatioBased(1))},
|
|
||||||
{`[opentelemetry]
|
|
||||||
ENABLED=true
|
|
||||||
TRACES_SAMPLER = not existing
|
|
||||||
TRACES_SAMPLER_ARG = badarg`, sdktrace.ParentBased(sdktrace.AlwaysSample())},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, sampler := range testSamplers {
|
|
||||||
cfg, err := NewConfigProviderFromData(sampler.IniCfg)
|
|
||||||
require.NoError(t, err)
|
|
||||||
loadOpenTelemetryFrom(cfg)
|
|
||||||
assert.Equal(t, sampler.Expected, OpenTelemetry.Sampler)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOpentelemetryBadConfigs(t *testing.T) {
|
|
||||||
defer test.MockProtect(&OpenTelemetry)()
|
|
||||||
iniStr := `
|
|
||||||
[opentelemetry]
|
|
||||||
ENABLED=true
|
|
||||||
|
|
||||||
[opentelemetry.exporter.otlp]
|
|
||||||
ENDPOINT = jaeger:4317/
|
|
||||||
`
|
|
||||||
cfg, err := NewConfigProviderFromData(iniStr)
|
|
||||||
require.NoError(t, err)
|
|
||||||
loadOpenTelemetryFrom(cfg)
|
|
||||||
|
|
||||||
assert.True(t, IsOpenTelemetryEnabled())
|
|
||||||
assert.Equal(t, "jaeger:4317/", OpenTelemetry.OtelTraces.Endpoint.String())
|
|
||||||
|
|
||||||
iniStr = ``
|
|
||||||
cfg, err = NewConfigProviderFromData(iniStr)
|
|
||||||
require.NoError(t, err)
|
|
||||||
loadOpenTelemetryFrom(cfg)
|
|
||||||
assert.False(t, IsOpenTelemetryEnabled())
|
|
||||||
|
|
||||||
iniStr = `
|
|
||||||
[opentelemetry]
|
|
||||||
ENABLED=true
|
|
||||||
SERVICE_NAME =
|
|
||||||
TRACES_SAMPLER = not existing one
|
|
||||||
[opentelemetry.exporter.otlp]
|
|
||||||
ENDPOINT = http://jaeger:4317/
|
|
||||||
|
|
||||||
TIMEOUT = abc
|
|
||||||
COMPRESSION = foo
|
|
||||||
HEADERS=%s=bar,foo=%h,foo
|
|
||||||
|
|
||||||
`
|
|
||||||
|
|
||||||
cfg, err = NewConfigProviderFromData(iniStr)
|
|
||||||
|
|
||||||
require.NoError(t, err)
|
|
||||||
loadOpenTelemetryFrom(cfg)
|
|
||||||
assert.True(t, IsOpenTelemetryEnabled())
|
|
||||||
assert.Equal(t, "forgejo", OpenTelemetry.ServiceName)
|
|
||||||
assert.Equal(t, 10*time.Second, OpenTelemetry.OtelTraces.Timeout)
|
|
||||||
assert.Equal(t, sdktrace.ParentBased(sdktrace.AlwaysSample()), OpenTelemetry.Sampler)
|
|
||||||
assert.Equal(t, "http://jaeger:4317/", OpenTelemetry.OtelTraces.Endpoint.String())
|
|
||||||
assert.Empty(t, OpenTelemetry.OtelTraces.Headers)
|
|
||||||
}
|
|
|
@ -150,7 +150,6 @@ func loadCommonSettingsFrom(cfg ConfigProvider) error {
|
||||||
loadAPIFrom(cfg)
|
loadAPIFrom(cfg)
|
||||||
loadBadgesFrom(cfg)
|
loadBadgesFrom(cfg)
|
||||||
loadMetricsFrom(cfg)
|
loadMetricsFrom(cfg)
|
||||||
loadOpenTelemetryFrom(cfg)
|
|
||||||
loadCamoFrom(cfg)
|
loadCamoFrom(cfg)
|
||||||
loadI18nFrom(cfg)
|
loadI18nFrom(cfg)
|
||||||
loadGitFrom(cfg)
|
loadGitFrom(cfg)
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
add support for basic request tracing with opentelemetry
|
|
|
@ -18,7 +18,6 @@ import (
|
||||||
"gitea.com/go-chi/session"
|
"gitea.com/go-chi/session"
|
||||||
"github.com/chi-middleware/proxy"
|
"github.com/chi-middleware/proxy"
|
||||||
chi "github.com/go-chi/chi/v5"
|
chi "github.com/go-chi/chi/v5"
|
||||||
"github.com/riandyrn/otelchi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProtocolMiddlewares returns HTTP protocol related middlewares, and it provides a global panic recovery
|
// ProtocolMiddlewares returns HTTP protocol related middlewares, and it provides a global panic recovery
|
||||||
|
@ -69,9 +68,6 @@ func ProtocolMiddlewares() (handlers []any) {
|
||||||
if setting.IsAccessLogEnabled() {
|
if setting.IsAccessLogEnabled() {
|
||||||
handlers = append(handlers, context.AccessLogger())
|
handlers = append(handlers, context.AccessLogger())
|
||||||
}
|
}
|
||||||
if setting.IsOpenTelemetryEnabled() {
|
|
||||||
handlers = append(handlers, otelchi.Middleware("forgejo"))
|
|
||||||
}
|
|
||||||
|
|
||||||
return handlers
|
return handlers
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ import (
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/markup"
|
"code.gitea.io/gitea/modules/markup"
|
||||||
"code.gitea.io/gitea/modules/markup/external"
|
"code.gitea.io/gitea/modules/markup/external"
|
||||||
"code.gitea.io/gitea/modules/opentelemetry"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/ssh"
|
"code.gitea.io/gitea/modules/ssh"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
|
@ -111,7 +110,6 @@ func InitWebInstallPage(ctx context.Context) {
|
||||||
|
|
||||||
// InitWebInstalled is for global installed configuration.
|
// InitWebInstalled is for global installed configuration.
|
||||||
func InitWebInstalled(ctx context.Context) {
|
func InitWebInstalled(ctx context.Context) {
|
||||||
mustInitCtx(ctx, opentelemetry.Init)
|
|
||||||
mustInitCtx(ctx, git.InitFull)
|
mustInitCtx(ctx, git.InitFull)
|
||||||
log.Info("Git version: %s (home: %s)", git.VersionInfo(), git.HomeDir())
|
log.Info("Git version: %s (home: %s)", git.VersionInfo(), git.HomeDir())
|
||||||
|
|
||||||
|
|
|
@ -4,23 +4,12 @@
|
||||||
package install
|
package install
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
"code.gitea.io/gitea/modules/opentelemetry"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/modules/test"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRoutes(t *testing.T) {
|
func TestRoutes(t *testing.T) {
|
||||||
|
@ -47,43 +36,3 @@ func TestRoutes(t *testing.T) {
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
unittest.MainTest(m)
|
unittest.MainTest(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOtelChi(t *testing.T) {
|
|
||||||
ServiceName := "forgejo-otelchi" + uuid.NewString()
|
|
||||||
|
|
||||||
otelURL, ok := os.LookupEnv("TEST_OTEL_URL")
|
|
||||||
if !ok {
|
|
||||||
t.Skip("TEST_OTEL_URL not set")
|
|
||||||
}
|
|
||||||
traceEndpoint, err := url.Parse(otelURL)
|
|
||||||
require.NoError(t, err)
|
|
||||||
config := &setting.OtelExporter{
|
|
||||||
Endpoint: traceEndpoint,
|
|
||||||
Protocol: "grpc",
|
|
||||||
}
|
|
||||||
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.Enabled, true)()
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.Traces, "otlp")() // Required due to lazy loading
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.ServiceName, ServiceName)()
|
|
||||||
defer test.MockVariableValue(&setting.OpenTelemetry.OtelTraces, config)()
|
|
||||||
|
|
||||||
require.NoError(t, opentelemetry.Init(context.Background()))
|
|
||||||
r := Routes()
|
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
req := httptest.NewRequest("GET", "/e/img/gitea.svg", nil)
|
|
||||||
r.ServeHTTP(w, req)
|
|
||||||
|
|
||||||
traceEndpoint.Host = traceEndpoint.Hostname() + ":16686"
|
|
||||||
traceEndpoint.Path = "/api/services"
|
|
||||||
|
|
||||||
require.EventuallyWithT(t, func(collect *assert.CollectT) {
|
|
||||||
resp, err := http.Get(traceEndpoint.String())
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
apiResponse, err := io.ReadAll(resp.Body)
|
|
||||||
require.NoError(t, err)
|
|
||||||
|
|
||||||
assert.Contains(collect, string(apiResponse), ServiceName)
|
|
||||||
}, 15*time.Second, 1*time.Second)
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue