mirror of
https://github.com/foomo/keel.git
synced 2026-10-06 15:16:59 +00:00
Merge pull request #300 from foomo/feature/telemetry
Test Branch / test (push) Has been cancelled
Test Branch / test (push) Has been cancelled
feat: telemetry
This commit is contained in:
@@ -155,7 +155,7 @@ actionlint:
|
||||
@actionlint
|
||||
|
||||
.PHONY: help
|
||||
# https://patorjk.com/software/taag/#p=display&f=Tmplr&t=keel&x=none&v=4&h=4&w=80&we=false
|
||||
# https://patorjk.com/software/taag/#p=display&f=Future+Smooth&t=keel&x=none&v=4&h=4&w=80&we=false
|
||||
## Show help text
|
||||
help: g=\033[0;32m
|
||||
help: b=\033[0;34m
|
||||
@@ -163,9 +163,9 @@ help: w=\033[0;90m
|
||||
help: e=\033[0m
|
||||
help:
|
||||
@echo "$(g)"
|
||||
@echo "┓ ┓"
|
||||
@echo "┃┏┏┓┏┓┃"
|
||||
@echo "┛┗┗ ┗ ┗"
|
||||
@echo "╷╭ ╭─╴╭─╴╷"
|
||||
@echo "├┴╮├╴ ├╴ │"
|
||||
@echo "╵ ╵╰─╴╰─╴╰─╴"
|
||||
@echo "with ❤ foomo by bestbytes"
|
||||
@echo "$(e)"
|
||||
@echo "$(b)Usage:$(e)\n make [task]"
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/foomo/keel/markdown"
|
||||
)
|
||||
|
||||
// Deprecated: will be removed in future releases
|
||||
func Readme() string {
|
||||
var (
|
||||
configRows [][]string
|
||||
|
||||
Vendored
+1
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/foomo/keel/markdown"
|
||||
)
|
||||
|
||||
// Deprecated: will be removed in future releases
|
||||
func Readme() string {
|
||||
var rows [][]string
|
||||
|
||||
|
||||
+13
-11
@@ -45,10 +45,11 @@ require (
|
||||
github.com/fatih/color v1.19.0 // indirect
|
||||
github.com/fbiville/markdown-table-formatter v0.3.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/foomo/go v0.14.1 // indirect
|
||||
github.com/foomo/goflux v0.4.4 // indirect
|
||||
github.com/foomo/gofuncy v0.2.0 // indirect
|
||||
github.com/foomo/go v0.16.0 // indirect
|
||||
github.com/foomo/goflux v0.6.0 // indirect
|
||||
github.com/foomo/gofuncy v0.4.0 // indirect
|
||||
github.com/foomo/gostandards v0.3.0 // indirect
|
||||
github.com/foomo/mongo-lock v0.2.0 // indirect
|
||||
github.com/foomo/opentelemetry-go v0.4.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.10.1 // indirect
|
||||
github.com/go-logr/logr v1.4.4 // indirect
|
||||
@@ -59,13 +60,13 @@ require (
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.15 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.16 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.22.0 // indirect
|
||||
github.com/grafana/otel-profiling-go v0.6.0 // indirect
|
||||
github.com/grafana/pyroscope-go v1.4.1 // indirect
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.11 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect
|
||||
github.com/hashicorp/consul/api v1.34.2 // indirect
|
||||
github.com/hashicorp/consul/api v1.34.3 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
@@ -79,7 +80,7 @@ require (
|
||||
github.com/klauspost/compress v1.19.1 // indirect
|
||||
github.com/lib/pq v1.12.3 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-colorable v0.1.15 // indirect
|
||||
github.com/mattn/go-isatty v0.0.22 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
@@ -120,7 +121,7 @@ require (
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/bridges/otelzap v0.19.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo v0.0.0-20260623174712-bbae83b5df0c // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/host v0.69.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/runtime v0.69.0 // indirect
|
||||
@@ -143,18 +144,19 @@ require (
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.54.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a // indirect
|
||||
golang.org/x/exp v0.0.0-20260529124908-c761662dc8c9 // indirect
|
||||
golang.org/x/mod v0.38.0 // indirect
|
||||
golang.org/x/net v0.57.0 // indirect
|
||||
golang.org/x/oauth2 v0.36.0 // indirect
|
||||
golang.org/x/sync v0.22.0 // indirect
|
||||
golang.org/x/sys v0.47.0 // indirect
|
||||
golang.org/x/text v0.40.0 // indirect
|
||||
golang.org/x/time v0.15.0 // indirect
|
||||
google.golang.org/api v0.278.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20260511170946-3700d4141b60 // indirect
|
||||
google.golang.org/api v0.282.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||
google.golang.org/grpc v1.81.1 // indirect
|
||||
google.golang.org/grpc v1.82.1 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
Generated
+38
-30
@@ -1,5 +1,5 @@
|
||||
charm.land/lipgloss/v2 v2.0.2 h1:xFolbF8JdpNkM2cEPTfXEcW1p6NRzOWTSamRfYEw8cs=
|
||||
charm.land/lipgloss/v2 v2.0.2/go.mod h1:KjPle2Qd3YmvP1KL5OMHiHysGcNwq6u83MUjYkFvEkM=
|
||||
charm.land/lipgloss/v2 v2.0.3 h1:yM2zJ4Cf5Y51b7RHIwioil4ApI/aypFXXVHSwlM6RzU=
|
||||
charm.land/lipgloss/v2 v2.0.3/go.mod h1:7myLU9iG/3xluAWzpY/fSxYYHCgoKTie7laxk6ATwXA=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
|
||||
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
|
||||
@@ -46,8 +46,8 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
|
||||
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260330092749-0f94982c930b h1:ASDO9RT6SNKTQN87jO2bRfxHFJq8cgeYdFzivY2gCeM=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260330092749-0f94982c930b/go.mod h1:Vo8TffMf0q7Uho/n8e6XpBZvOWtd3g39yX+9P5rRutA=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260416161146-9c68a866306c h1:a+Q3cOt8vEb6ETG/st32Qjm8R5fdI9wSKb3tqPISnoY=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260416161146-9c68a866306c/go.mod h1:bAAz7dh/FTYfC+oiHavL4mX1tOIBZ0ZwYjSi3qE6ivM=
|
||||
github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI=
|
||||
github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ=
|
||||
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
||||
@@ -102,14 +102,16 @@ github.com/fbiville/markdown-table-formatter v0.3.0 h1:PIm1UNgJrFs8q1htGTw+wnnNY
|
||||
github.com/fbiville/markdown-table-formatter v0.3.0/go.mod h1:q89TDtSEVDdTaufgSbfHpNVdPU/bmfvqNkrC5HagmLY=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/foomo/go v0.14.1 h1:33ePCyAClSj2pqcEI9isyiEe1qoMd6c+Mn0ClLntSoM=
|
||||
github.com/foomo/go v0.14.1/go.mod h1:jeSB/atkoqSoJ3+ak0+b/Xtj7IMyDj1odzJroudT7Dw=
|
||||
github.com/foomo/goflux v0.4.4 h1:T7QhIPdZze3bNEeNjdEAzBV08/ikEgmTmK3maWucAo4=
|
||||
github.com/foomo/goflux v0.4.4/go.mod h1:c2qy02JR9Y5qlVl49nDSEipCQENbGhDZzjT8p72G7Xs=
|
||||
github.com/foomo/gofuncy v0.2.0 h1:fanMIpHocWfoP+u8sevF+Qb/gEh38QeiS6FjeXB+Sx0=
|
||||
github.com/foomo/gofuncy v0.2.0/go.mod h1:WnqsC/Ku/19tk0LYHVG8z9tsT9duKqpxHMiJioznv1M=
|
||||
github.com/foomo/go v0.16.0 h1:Hw2rl0ieMB+s9NK8+MuIHzD22h48whyoKV+CA+lFG1k=
|
||||
github.com/foomo/go v0.16.0/go.mod h1:jeSB/atkoqSoJ3+ak0+b/Xtj7IMyDj1odzJroudT7Dw=
|
||||
github.com/foomo/goflux v0.6.0 h1:O9PYXGevBi2rymxZ+AWm2Kollced45vb4mwz1xWQX1M=
|
||||
github.com/foomo/goflux v0.6.0/go.mod h1:xJZGTK4gZnmiZ5NqcKfTAHtXt9uBB27fRdrH0Voy+jI=
|
||||
github.com/foomo/gofuncy v0.4.0 h1:wxfFOQSp+eZYy9YFXY7A8PPu0n51t4Xhvd6tOm0OSSs=
|
||||
github.com/foomo/gofuncy v0.4.0/go.mod h1:ulEUpkz38K6trv71GM7fHjaUqa/NbWOZUE5MAbfe/Kk=
|
||||
github.com/foomo/gostandards v0.3.0 h1:Ev88Tdu0+52UH/d0l2KcAWx542A13o42d++LSTG0DC4=
|
||||
github.com/foomo/gostandards v0.3.0/go.mod h1:8hJ56tpyFAVwavs5FuUF3po7Bq7hOTkQ1+DzFi4GCWg=
|
||||
github.com/foomo/mongo-lock v0.2.0 h1:xURP2FijZ/feACB5YL1UKUXk23M+x5L+yltEK+sJm0g=
|
||||
github.com/foomo/mongo-lock v0.2.0/go.mod h1:5LMCz8IeaTMCWcgh+aPoDeIjY1qpu8MXbx+FNrGAUFA=
|
||||
github.com/foomo/opentelemetry-go v0.4.0 h1:UQneCUSokIYJXzFUKQSI8rlelbUuf6atgSZMhvD+Nzo=
|
||||
github.com/foomo/opentelemetry-go v0.4.0/go.mod h1:R3Se/rc5FRAs4ThE6JQ9Oq3cOLo2MOsUzZLJxZquwxA=
|
||||
github.com/foomo/opentelemetry-go/exporters/glossy/glossymetric v0.4.0 h1:o2EScdH3ZgIU2sTHbOnCRXsMr6wTHjAYx63rriQRmtU=
|
||||
@@ -137,6 +139,8 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
|
||||
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
@@ -170,8 +174,8 @@ github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
|
||||
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.15 h1:xolVQTEXusUcAA5UgtyRLjelpFFHWlPQ4XfWGc7MBas=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.15/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.16 h1:F/VPrx0YPBdksZJQdCAp0WUsqnNmZpUZszzfYt0M5Dw=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.16/go.mod h1:9Yb0eAkH/Xqhvv3zbeKf/+wMJqCeocWc6KIhDvEAuYE=
|
||||
github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4=
|
||||
github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY=
|
||||
github.com/grafana/otel-profiling-go v0.6.0 h1:W7lOZaJj4IJISXMcM1UBk3fJF3tzF2OD6MJBJaQp1H8=
|
||||
@@ -182,8 +186,8 @@ github.com/grafana/pyroscope-go/godeltaprof v0.1.11 h1:el5LYpXissAiCKZ5/6yjlr6mh
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.11/go.mod h1:jl1V8M4cWsXciROCPIDDG7CtjSjT/ECbp6eLVuMxYRI=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 h1:5VipnvEpbqr2gA2VbM+nYVbkIF28c5ZQfqCBQ5g2xfk=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0/go.mod h1:Hyl3n6Twe1hvtd9XUXDec4pTvgMSEixRuQKPTMH2bNs=
|
||||
github.com/hashicorp/consul/api v1.34.2 h1:B5jqSSKwWyY8U8WiGS5vmPEPkkF0bAvrECykdZkDR80=
|
||||
github.com/hashicorp/consul/api v1.34.2/go.mod h1:+gAdHQa2zvgYX3ZfcgITtnYCSj6AgS/cgotvCKaE+b8=
|
||||
github.com/hashicorp/consul/api v1.34.3 h1:OiZaQnwkS6uvutie3CF6NFXj8uScNezDlsU9MEqKT0s=
|
||||
github.com/hashicorp/consul/api v1.34.3/go.mod h1:A4wKd7yw7Wz4zn07p74+o0bLBi5dXsSDMMcMCEinY40=
|
||||
github.com/hashicorp/consul/sdk v0.18.1 h1:RDTeBvAeOveI2xI86sV+8WkaN7OkP4zz+cG3fOobDCM=
|
||||
github.com/hashicorp/consul/sdk v0.18.1/go.mod h1:XdP2tEJmAvlK4jgoKTTtohGkRJlS4mU44mv9/sjU21s=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@@ -258,8 +262,8 @@ github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8S
|
||||
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY=
|
||||
github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
|
||||
@@ -403,6 +407,8 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/testcontainers/testcontainers-go v0.43.0 h1:oEQx5MW2DGd9z3AeEQfB2lPM0eLs7ztyaGRu75bFo5A=
|
||||
github.com/testcontainers/testcontainers-go v0.43.0/go.mod h1:+VxkT2NQnKOZPKi6praMuMKYHYyOGXr0XSBSlSMCzFo=
|
||||
github.com/testcontainers/testcontainers-go/modules/mongodb v0.43.0 h1:RJlAAz8dv61icyHvFmrr1xZHJEWZdvBfVBAU6wnmGPM=
|
||||
github.com/testcontainers/testcontainers-go/modules/mongodb v0.43.0/go.mod h1:1zaDEZyV1SK+mpz83tmB2KthF6DHaS4Y+lRvy3d2XiE=
|
||||
github.com/testcontainers/testcontainers-go/modules/nats v0.43.0 h1:n1KcDXc18F687ODlTra411qWs+U+SH8VdnMM4kwpGo0=
|
||||
github.com/testcontainers/testcontainers-go/modules/nats v0.43.0/go.mod h1:nIBpPkiorwXM5LDOQKTD9Osxr/cWv1W4FcAx43kM7jY=
|
||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||
@@ -445,8 +451,8 @@ go.opentelemetry.io/contrib/bridges/otelzap v0.19.0 h1:48Eq3xxFx2KlL/tF7lnl42kKJ
|
||||
go.opentelemetry.io/contrib/bridges/otelzap v0.19.0/go.mod h1:cQbV77F0u6HmtZPiQD9oxp2esaOEb4uLqIta6OFIKOk=
|
||||
go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo v0.0.0-20260623174712-bbae83b5df0c h1:etHDCLakSn0jdNgLzYZ0zGKiwaNMof0R/uA+hVqIXQo=
|
||||
go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo v0.0.0-20260623174712-bbae83b5df0c/go.mod h1:VgtIsrVXKo8KmG2sFvQazHcQ98P2FHQ+ZePXtpTPjqs=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0 h1:2yEATaop1/a1I4psnSLgWVPLWwCzkqWakgJy7xTDVy0=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0/go.mod h1:D7J12YRapIekYyPWgGPlA/23pRmpSEZC5xJC/TTLI9U=
|
||||
go.opentelemetry.io/contrib/instrumentation/host v0.69.0 h1:N/wKAdIOKd9U4bwiwY3j95e2ZR48onTMR/NI/SZQ/a4=
|
||||
go.opentelemetry.io/contrib/instrumentation/host v0.69.0/go.mod h1:rE1Bxmu3mwcmyTJV4EQdJ/C6zCUnuT9jCiinhRXLAXc=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 h1:8tvICD4vSTOOsNrsI4Ljf6C+6UKvpTEH5XY3JMoyPoo=
|
||||
@@ -516,13 +522,13 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
||||
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
||||
golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a h1:+3jdDGGB8NGb1Zktc737jlt3/A5f6UlwSzmvqUuufxw=
|
||||
golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a/go.mod h1:d2fgXJLVs4dYDHUk5lwMIfzRzSrWCfGZb0ZqeLa/Vcw=
|
||||
golang.org/x/exp v0.0.0-20260529124908-c761662dc8c9 h1:4d4PbuBNwaxMXkXI8yiIYjydtMU+04RHeuSxJdgKftM=
|
||||
golang.org/x/exp v0.0.0-20260529124908-c761662dc8c9/go.mod h1:d2fgXJLVs4dYDHUk5lwMIfzRzSrWCfGZb0ZqeLa/Vcw=
|
||||
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.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
||||
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
||||
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
|
||||
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -591,25 +597,25 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
|
||||
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
|
||||
golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
|
||||
golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
|
||||
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=
|
||||
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/api v0.278.0 h1:W7jiRvRi53VYFfZ/HoZjQBtJk7gOFbHD8ot1RzVZU6E=
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/api v0.282.0 h1:WmJiSVqUnKqJCpJOx7YADbXaC+9DDsnGSfllFSj7R2I=
|
||||
google.golang.org/api v0.282.0/go.mod h1:6Wssta4c5n9qHq5CBhmlai5h/PUa1djdDAIhYEHyvcM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20260511170946-3700d4141b60 h1:rhBdfmsOlOZIvz3Y5/BdUzPg2CkO8L7QQPKj96B8554=
|
||||
google.golang.org/genproto v0.0.0-20260511170946-3700d4141b60/go.mod h1:8xo2Pj1b20ZOCpzlU3B9qieMwVIAXx1QVZWLMlPL6sM=
|
||||
google.golang.org/genproto v0.0.0-20260526163538-3dc84a4a5aaa h1:mfj8IS4EA4VAR9a6QDVxTQkLY64iBybb5QI1B4pXrpE=
|
||||
google.golang.org/genproto v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:fuT7yonGw1Iq2oa+YC0fyqPPQJkgo/54gPNC6VitOkI=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
|
||||
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
|
||||
google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE=
|
||||
google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
|
||||
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=
|
||||
@@ -631,3 +637,5 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
|
||||
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
|
||||
|
||||
@@ -5,9 +5,9 @@ go 1.26.0
|
||||
require (
|
||||
github.com/avast/retry-go/v4 v4.7.0
|
||||
github.com/fbiville/markdown-table-formatter v0.3.0
|
||||
github.com/foomo/go v0.14.1
|
||||
github.com/foomo/goflux v0.4.4
|
||||
github.com/foomo/gofuncy v0.2.0
|
||||
github.com/foomo/go v0.16.0
|
||||
github.com/foomo/goflux v0.6.0
|
||||
github.com/foomo/gofuncy v0.4.0
|
||||
github.com/foomo/gostandards v0.3.0
|
||||
github.com/foomo/opentelemetry-go v0.4.0
|
||||
github.com/go-logr/logr v1.4.4
|
||||
@@ -48,6 +48,7 @@ require (
|
||||
go.opentelemetry.io/otel/sdk/log v0.20.0
|
||||
go.opentelemetry.io/otel/sdk/metric v1.44.0
|
||||
go.opentelemetry.io/otel/trace v1.44.0
|
||||
go.uber.org/goleak v1.3.0
|
||||
go.uber.org/zap v1.28.0
|
||||
golang.org/x/crypto v0.54.0
|
||||
golang.org/x/sync v0.22.0
|
||||
@@ -67,7 +68,6 @@ require (
|
||||
github.com/buger/jsonparser v1.1.2 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.11.7 // indirect
|
||||
github.com/coreos/go-semver v0.3.1 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.7.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
@@ -83,11 +83,11 @@ require (
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.15 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.16 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.22.0 // indirect
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.11 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 // indirect
|
||||
github.com/hashicorp/consul/api v1.34.2 // indirect
|
||||
github.com/hashicorp/consul/api v1.34.3 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-hclog v1.6.3 // indirect
|
||||
@@ -99,14 +99,14 @@ require (
|
||||
github.com/hashicorp/serf v0.10.2 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-colorable v0.1.15 // indirect
|
||||
github.com/mattn/go-isatty v0.0.22 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nats-io/nats.go v1.52.0 // indirect
|
||||
github.com/nats-io/nkeys v0.4.15 // indirect
|
||||
github.com/nats-io/nkeys v0.4.16 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/pb33f/ordered-map/v2 v2.3.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.3.1 // indirect
|
||||
@@ -119,7 +119,7 @@ require (
|
||||
github.com/prometheus/procfs v0.21.1 // indirect
|
||||
github.com/sagikazarmark/crypt v0.31.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.12.0 // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.26.4 // indirect
|
||||
github.com/shirou/gopsutil/v4 v4.26.5 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
@@ -132,22 +132,23 @@ require (
|
||||
go.etcd.io/etcd/client/v2 v2.305.30 // indirect
|
||||
go.etcd.io/etcd/client/v3 v3.6.11 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.2 // indirect
|
||||
golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a // indirect
|
||||
golang.org/x/exp v0.0.0-20260529124908-c761662dc8c9 // indirect
|
||||
golang.org/x/net v0.57.0 // indirect
|
||||
golang.org/x/oauth2 v0.36.0 // indirect
|
||||
golang.org/x/sys v0.47.0 // indirect
|
||||
golang.org/x/text v0.40.0 // indirect
|
||||
golang.org/x/time v0.15.0 // indirect
|
||||
google.golang.org/api v0.278.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20260511170946-3700d4141b60 // indirect
|
||||
golang.org/x/tools v0.48.0 // indirect
|
||||
google.golang.org/api v0.282.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||
google.golang.org/grpc v1.81.1 // indirect
|
||||
google.golang.org/grpc v1.82.1 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
charm.land/lipgloss/v2 v2.0.2 h1:xFolbF8JdpNkM2cEPTfXEcW1p6NRzOWTSamRfYEw8cs=
|
||||
charm.land/lipgloss/v2 v2.0.2/go.mod h1:KjPle2Qd3YmvP1KL5OMHiHysGcNwq6u83MUjYkFvEkM=
|
||||
charm.land/lipgloss/v2 v2.0.3 h1:yM2zJ4Cf5Y51b7RHIwioil4ApI/aypFXXVHSwlM6RzU=
|
||||
charm.land/lipgloss/v2 v2.0.3/go.mod h1:7myLU9iG/3xluAWzpY/fSxYYHCgoKTie7laxk6ATwXA=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
|
||||
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
|
||||
@@ -38,8 +38,8 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
|
||||
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260330092749-0f94982c930b h1:ASDO9RT6SNKTQN87jO2bRfxHFJq8cgeYdFzivY2gCeM=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260330092749-0f94982c930b/go.mod h1:Vo8TffMf0q7Uho/n8e6XpBZvOWtd3g39yX+9P5rRutA=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260416161146-9c68a866306c h1:a+Q3cOt8vEb6ETG/st32Qjm8R5fdI9wSKb3tqPISnoY=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260416161146-9c68a866306c/go.mod h1:bAAz7dh/FTYfC+oiHavL4mX1tOIBZ0ZwYjSi3qE6ivM=
|
||||
github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI=
|
||||
github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ=
|
||||
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
||||
@@ -78,12 +78,12 @@ github.com/fbiville/markdown-table-formatter v0.3.0 h1:PIm1UNgJrFs8q1htGTw+wnnNY
|
||||
github.com/fbiville/markdown-table-formatter v0.3.0/go.mod h1:q89TDtSEVDdTaufgSbfHpNVdPU/bmfvqNkrC5HagmLY=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/foomo/go v0.14.1 h1:33ePCyAClSj2pqcEI9isyiEe1qoMd6c+Mn0ClLntSoM=
|
||||
github.com/foomo/go v0.14.1/go.mod h1:jeSB/atkoqSoJ3+ak0+b/Xtj7IMyDj1odzJroudT7Dw=
|
||||
github.com/foomo/goflux v0.4.4 h1:T7QhIPdZze3bNEeNjdEAzBV08/ikEgmTmK3maWucAo4=
|
||||
github.com/foomo/goflux v0.4.4/go.mod h1:c2qy02JR9Y5qlVl49nDSEipCQENbGhDZzjT8p72G7Xs=
|
||||
github.com/foomo/gofuncy v0.2.0 h1:fanMIpHocWfoP+u8sevF+Qb/gEh38QeiS6FjeXB+Sx0=
|
||||
github.com/foomo/gofuncy v0.2.0/go.mod h1:WnqsC/Ku/19tk0LYHVG8z9tsT9duKqpxHMiJioznv1M=
|
||||
github.com/foomo/go v0.16.0 h1:Hw2rl0ieMB+s9NK8+MuIHzD22h48whyoKV+CA+lFG1k=
|
||||
github.com/foomo/go v0.16.0/go.mod h1:jeSB/atkoqSoJ3+ak0+b/Xtj7IMyDj1odzJroudT7Dw=
|
||||
github.com/foomo/goflux v0.6.0 h1:O9PYXGevBi2rymxZ+AWm2Kollced45vb4mwz1xWQX1M=
|
||||
github.com/foomo/goflux v0.6.0/go.mod h1:xJZGTK4gZnmiZ5NqcKfTAHtXt9uBB27fRdrH0Voy+jI=
|
||||
github.com/foomo/gofuncy v0.4.0 h1:wxfFOQSp+eZYy9YFXY7A8PPu0n51t4Xhvd6tOm0OSSs=
|
||||
github.com/foomo/gofuncy v0.4.0/go.mod h1:ulEUpkz38K6trv71GM7fHjaUqa/NbWOZUE5MAbfe/Kk=
|
||||
github.com/foomo/gostandards v0.3.0 h1:Ev88Tdu0+52UH/d0l2KcAWx542A13o42d++LSTG0DC4=
|
||||
github.com/foomo/gostandards v0.3.0/go.mod h1:8hJ56tpyFAVwavs5FuUF3po7Bq7hOTkQ1+DzFi4GCWg=
|
||||
github.com/foomo/opentelemetry-go v0.4.0 h1:UQneCUSokIYJXzFUKQSI8rlelbUuf6atgSZMhvD+Nzo=
|
||||
@@ -144,8 +144,8 @@ github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
|
||||
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.15 h1:xolVQTEXusUcAA5UgtyRLjelpFFHWlPQ4XfWGc7MBas=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.15/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.16 h1:F/VPrx0YPBdksZJQdCAp0WUsqnNmZpUZszzfYt0M5Dw=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.16/go.mod h1:9Yb0eAkH/Xqhvv3zbeKf/+wMJqCeocWc6KIhDvEAuYE=
|
||||
github.com/googleapis/gax-go/v2 v2.22.0 h1:PjIWBpgGIVKGoCXuiCoP64altEJCj3/Ei+kSU5vlZD4=
|
||||
github.com/googleapis/gax-go/v2 v2.22.0/go.mod h1:irWBbALSr0Sk3qlqb9SyJ1h68WjgeFuiOzI4Rqw5+aY=
|
||||
github.com/grafana/otel-profiling-go v0.6.0 h1:W7lOZaJj4IJISXMcM1UBk3fJF3tzF2OD6MJBJaQp1H8=
|
||||
@@ -156,8 +156,8 @@ github.com/grafana/pyroscope-go/godeltaprof v0.1.11 h1:el5LYpXissAiCKZ5/6yjlr6mh
|
||||
github.com/grafana/pyroscope-go/godeltaprof v0.1.11/go.mod h1:jl1V8M4cWsXciROCPIDDG7CtjSjT/ECbp6eLVuMxYRI=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0 h1:5VipnvEpbqr2gA2VbM+nYVbkIF28c5ZQfqCBQ5g2xfk=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.29.0/go.mod h1:Hyl3n6Twe1hvtd9XUXDec4pTvgMSEixRuQKPTMH2bNs=
|
||||
github.com/hashicorp/consul/api v1.34.2 h1:B5jqSSKwWyY8U8WiGS5vmPEPkkF0bAvrECykdZkDR80=
|
||||
github.com/hashicorp/consul/api v1.34.2/go.mod h1:+gAdHQa2zvgYX3ZfcgITtnYCSj6AgS/cgotvCKaE+b8=
|
||||
github.com/hashicorp/consul/api v1.34.3 h1:OiZaQnwkS6uvutie3CF6NFXj8uScNezDlsU9MEqKT0s=
|
||||
github.com/hashicorp/consul/api v1.34.3/go.mod h1:A4wKd7yw7Wz4zn07p74+o0bLBi5dXsSDMMcMCEinY40=
|
||||
github.com/hashicorp/consul/sdk v0.18.1 h1:RDTeBvAeOveI2xI86sV+8WkaN7OkP4zz+cG3fOobDCM=
|
||||
github.com/hashicorp/consul/sdk v0.18.1/go.mod h1:XdP2tEJmAvlK4jgoKTTtohGkRJlS4mU44mv9/sjU21s=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@@ -228,8 +228,8 @@ github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e h1:Q6MvJtQK/iRcRt
|
||||
github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY=
|
||||
github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
|
||||
@@ -258,8 +258,8 @@ 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/nats-io/nats.go v1.52.0 h1:n3avV4VBsCgsdwh71TppsTwtv+QdPs7ntSKM8qJLGsc=
|
||||
github.com/nats-io/nats.go v1.52.0/go.mod h1:26HypzazeOkyO3/mqd1zZd53STJN0EjCYF9Uy2ZOBno=
|
||||
github.com/nats-io/nkeys v0.4.15 h1:JACV5jRVO9V856KOapQ7x+EY8Jo3qw1vJt/9Jpwzkk4=
|
||||
github.com/nats-io/nkeys v0.4.15/go.mod h1:CpMchTXC9fxA5zrMo4KpySxNjiDVvr8ANOSZdiNfUrs=
|
||||
github.com/nats-io/nkeys v0.4.16 h1:rd5oAuLOb8mnAycB0xleuEBNS1pVVnN0fv/FF34Eypg=
|
||||
github.com/nats-io/nkeys v0.4.16/go.mod h1:llLgWoI0o4z/Q57q2R1kHfmocyhGV6VG/U18Glg1Afs=
|
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
|
||||
@@ -318,8 +318,8 @@ github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88ee
|
||||
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shirou/gopsutil/v4 v4.26.4 h1:B4SXVbcwTyrocPHEmWBC4uCYr4Xcu3MK1TXqbprAOWY=
|
||||
github.com/shirou/gopsutil/v4 v4.26.4/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ=
|
||||
github.com/shirou/gopsutil/v4 v4.26.5 h1:RPcBXkpz7kOj9PqGFQOlBPZHsyaPvPVQc098y9RmCNM=
|
||||
github.com/shirou/gopsutil/v4 v4.26.5/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ=
|
||||
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=
|
||||
@@ -374,8 +374,8 @@ go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/bridges/otelzap v0.19.0 h1:48Eq3xxFx2KlL/tF7lnl42kKJBDlhNTLRzv0h154JnM=
|
||||
go.opentelemetry.io/contrib/bridges/otelzap v0.19.0/go.mod h1:cQbV77F0u6HmtZPiQD9oxp2esaOEb4uLqIta6OFIKOk=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0 h1:0Qx7VGBacMm9ZENQ7TnNObTYI4ShC+lHI16seduaxZo=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.68.0/go.mod h1:Sje3i3MjSPKTSPvVWCaL8ugBzJwik3u4smCjUeuupqg=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0 h1:2yEATaop1/a1I4psnSLgWVPLWwCzkqWakgJy7xTDVy0=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.69.0/go.mod h1:D7J12YRapIekYyPWgGPlA/23pRmpSEZC5xJC/TTLI9U=
|
||||
go.opentelemetry.io/contrib/instrumentation/host v0.69.0 h1:N/wKAdIOKd9U4bwiwY3j95e2ZR48onTMR/NI/SZQ/a4=
|
||||
go.opentelemetry.io/contrib/instrumentation/host v0.69.0/go.mod h1:rE1Bxmu3mwcmyTJV4EQdJ/C6zCUnuT9jCiinhRXLAXc=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 h1:8tvICD4vSTOOsNrsI4Ljf6C+6UKvpTEH5XY3JMoyPoo=
|
||||
@@ -444,12 +444,12 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
||||
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
||||
golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a h1:+3jdDGGB8NGb1Zktc737jlt3/A5f6UlwSzmvqUuufxw=
|
||||
golang.org/x/exp v0.0.0-20260508232706-74f9aab9d74a/go.mod h1:d2fgXJLVs4dYDHUk5lwMIfzRzSrWCfGZb0ZqeLa/Vcw=
|
||||
golang.org/x/exp v0.0.0-20260529124908-c761662dc8c9 h1:4d4PbuBNwaxMXkXI8yiIYjydtMU+04RHeuSxJdgKftM=
|
||||
golang.org/x/exp v0.0.0-20260529124908-c761662dc8c9/go.mod h1:d2fgXJLVs4dYDHUk5lwMIfzRzSrWCfGZb0ZqeLa/Vcw=
|
||||
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.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
||||
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
||||
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
|
||||
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -506,25 +506,25 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
|
||||
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
|
||||
golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
|
||||
golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
|
||||
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=
|
||||
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/api v0.278.0 h1:W7jiRvRi53VYFfZ/HoZjQBtJk7gOFbHD8ot1RzVZU6E=
|
||||
google.golang.org/api v0.278.0/go.mod h1:B9TqLBwJqVjp1mtt7WeoQwWRwvu/400y5lETOql+giQ=
|
||||
google.golang.org/api v0.282.0 h1:WmJiSVqUnKqJCpJOx7YADbXaC+9DDsnGSfllFSj7R2I=
|
||||
google.golang.org/api v0.282.0/go.mod h1:6Wssta4c5n9qHq5CBhmlai5h/PUa1djdDAIhYEHyvcM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20260511170946-3700d4141b60 h1:rhBdfmsOlOZIvz3Y5/BdUzPg2CkO8L7QQPKj96B8554=
|
||||
google.golang.org/genproto v0.0.0-20260511170946-3700d4141b60/go.mod h1:8xo2Pj1b20ZOCpzlU3B9qieMwVIAXx1QVZWLMlPL6sM=
|
||||
google.golang.org/genproto v0.0.0-20260526163538-3dc84a4a5aaa h1:mfj8IS4EA4VAR9a6QDVxTQkLY64iBybb5QI1B4pXrpE=
|
||||
google.golang.org/genproto v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:fuT7yonGw1Iq2oa+YC0fyqPPQJkgo/54gPNC6VitOkI=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
|
||||
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
|
||||
google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE=
|
||||
google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
|
||||
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=
|
||||
|
||||
@@ -20,7 +20,7 @@ require (
|
||||
github.com/ebitengine/purego v0.10.1 // indirect
|
||||
github.com/fbiville/markdown-table-formatter v0.3.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/foomo/go v0.14.1 // indirect
|
||||
github.com/foomo/go v0.16.0 // indirect
|
||||
github.com/foomo/gostandards v0.3.0 // indirect
|
||||
github.com/foomo/opentelemetry-go v0.4.0 // indirect
|
||||
github.com/go-logr/logr v1.4.4 // indirect
|
||||
|
||||
Generated
+2
-2
@@ -19,8 +19,8 @@ github.com/fbiville/markdown-table-formatter v0.3.0 h1:PIm1UNgJrFs8q1htGTw+wnnNY
|
||||
github.com/fbiville/markdown-table-formatter v0.3.0/go.mod h1:q89TDtSEVDdTaufgSbfHpNVdPU/bmfvqNkrC5HagmLY=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/foomo/go v0.14.1 h1:33ePCyAClSj2pqcEI9isyiEe1qoMd6c+Mn0ClLntSoM=
|
||||
github.com/foomo/go v0.14.1/go.mod h1:jeSB/atkoqSoJ3+ak0+b/Xtj7IMyDj1odzJroudT7Dw=
|
||||
github.com/foomo/go v0.16.0 h1:Hw2rl0ieMB+s9NK8+MuIHzD22h48whyoKV+CA+lFG1k=
|
||||
github.com/foomo/go v0.16.0/go.mod h1:jeSB/atkoqSoJ3+ak0+b/Xtj7IMyDj1odzJroudT7Dw=
|
||||
github.com/foomo/gostandards v0.3.0 h1:Ev88Tdu0+52UH/d0l2KcAWx542A13o42d++LSTG0DC4=
|
||||
github.com/foomo/gostandards v0.3.0/go.mod h1:8hJ56tpyFAVwavs5FuUF3po7Bq7hOTkQ1+DzFi4GCWg=
|
||||
github.com/foomo/gotsrpc/v2 v2.16.1 h1:ih/YRUJpO3DOpw6cWXOVS4b6nOmfXxF+zudptxYFLxs=
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package gotsrpc
|
||||
|
||||
type GoRPCClient interface {
|
||||
Start()
|
||||
Stop()
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package gotsrpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type GoRPCClientService struct {
|
||||
client GoRPCClient
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func NewGoRPCClientService(client GoRPCClient) *GoRPCClientService {
|
||||
return &GoRPCClientService{
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *GoRPCClientService) Start(ctx context.Context) error {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
s.cancel = cancel
|
||||
s.client.Start()
|
||||
<-ctx.Done()
|
||||
s.client.Stop()
|
||||
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
func (s *GoRPCClientService) Close(ctx context.Context) error {
|
||||
if s.cancel != nil {
|
||||
s.cancel()
|
||||
s.cancel = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package gotsrpc
|
||||
|
||||
type GoRPCProxy interface {
|
||||
Start() error
|
||||
Stop()
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package gotsrpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type GoRPCProxyService struct {
|
||||
proxy GoRPCProxy
|
||||
cancel context.CancelFunc
|
||||
}
|
||||
|
||||
func NewGoRPCProxyService(proxy GoRPCProxy) *GoRPCProxyService {
|
||||
return &GoRPCProxyService{
|
||||
proxy: proxy,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *GoRPCProxyService) Start(ctx context.Context) error {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
|
||||
s.cancel = cancel
|
||||
if err := s.proxy.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
<-ctx.Done()
|
||||
s.proxy.Stop()
|
||||
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
func (s *GoRPCProxyService) Close(ctx context.Context) error {
|
||||
if s.cancel != nil {
|
||||
s.cancel()
|
||||
s.cancel = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"github.com/foomo/keel/telemetry"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.41.0"
|
||||
"go.uber.org/zap"
|
||||
@@ -79,6 +80,8 @@ func TelemetryWithPayloadAttributeDisabled(v bool) TelemetryOption {
|
||||
}
|
||||
|
||||
// Telemetry middleware
|
||||
//
|
||||
// Deprecated: use gotsrpc v3 as includes otel
|
||||
func Telemetry(opts ...TelemetryOption) keelhttp.Middleware {
|
||||
options := DefaultTelemetryOptions()
|
||||
|
||||
@@ -92,6 +95,8 @@ func Telemetry(opts ...TelemetryOption) keelhttp.Middleware {
|
||||
}
|
||||
|
||||
// TelemetryWithOptions middleware
|
||||
//
|
||||
// Deprecated: use gotsrpc v3 as includes otel
|
||||
func TelemetryWithOptions(opts TelemetryOptions) keelhttp.Middleware {
|
||||
m, err := gotsrpcconv.NewExecutionDuration(
|
||||
opts.meter,
|
||||
@@ -128,21 +133,19 @@ func TelemetryWithOptions(opts TelemetryOptions) keelhttp.Middleware {
|
||||
return func(l *zap.Logger, name string, next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
*r = *gotsrpc.RequestWithStatsContext(r)
|
||||
sp := telemetry.SpanFromContext(r.Context())
|
||||
|
||||
ctx := telemetry.Ctx(r.Context())
|
||||
ctx.AddSpanEvent("GOTSRPC Telemetry")
|
||||
|
||||
r = r.WithContext(ctx)
|
||||
sp.AddEvent("GOTSRPC Telemetry")
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
|
||||
if stats, ok := gotsrpc.GetStatsForRequest(r); ok {
|
||||
if !opts.PayloadAttributeDisabled {
|
||||
ctx.SetSpanAttributes(keelsemconv.GoTSRPCPayload(sanitizePayload(r)))
|
||||
sp.SetAttributes(keelsemconv.GoTSRPCPayload(sanitizePayload(r)))
|
||||
}
|
||||
|
||||
// override span name
|
||||
ctx.SetSpanName(fmt.Sprintf("%s/%s", stats.Service, stats.Func))
|
||||
sp.SetName(fmt.Sprintf("%s/%s", stats.Service, stats.Func))
|
||||
|
||||
// define default attributes
|
||||
attrs := []attribute.KeyValue{
|
||||
@@ -153,25 +156,25 @@ func TelemetryWithOptions(opts TelemetryOptions) keelhttp.Middleware {
|
||||
}
|
||||
|
||||
// add trace attributes
|
||||
ctx.SetSpanAttributes(append(attrs,
|
||||
sp.SetAttributes(append(attrs,
|
||||
keelsemconv.GoTSRPCMarshalling(stats.Marshalling.Milliseconds()),
|
||||
keelsemconv.GoTSRPCUnmarshalling(stats.Unmarshalling.Milliseconds()),
|
||||
)...)
|
||||
|
||||
if stats.ErrorCode != 0 {
|
||||
ctx.SetSpanStatusError(stats.ErrorMessage)
|
||||
ctx.SetSpanAttributes(keelsemconv.GoTSRPCErrorCode(stats.ErrorCode))
|
||||
sp.SetStatus(codes.Error, stats.ErrorMessage)
|
||||
sp.SetAttributes(keelsemconv.GoTSRPCErrorCode(stats.ErrorCode))
|
||||
}
|
||||
|
||||
if stats.ErrorType != "" {
|
||||
ctx.SetSpanAttributes(keelsemconv.GoTSRPCErrorType(stats.ErrorType))
|
||||
sp.SetAttributes(keelsemconv.GoTSRPCErrorType(stats.ErrorType))
|
||||
}
|
||||
|
||||
if stats.ErrorMessage != "" {
|
||||
ctx.SetSpanAttributes(keelsemconv.GoTSRPCErrorMessage(stats.ErrorMessage))
|
||||
sp.SetAttributes(keelsemconv.GoTSRPCErrorMessage(stats.ErrorMessage))
|
||||
}
|
||||
|
||||
m.Record(ctx,
|
||||
m.Record(r.Context(),
|
||||
stats.Execution.Seconds(),
|
||||
stats.Package,
|
||||
stats.Service,
|
||||
|
||||
@@ -5,8 +5,8 @@ go 1.26.0
|
||||
replace github.com/foomo/keel => ../../
|
||||
|
||||
require (
|
||||
github.com/foomo/go v0.14.1
|
||||
github.com/foomo/gofuncy v0.2.0
|
||||
github.com/foomo/go v0.16.0
|
||||
github.com/foomo/gofuncy v0.4.0
|
||||
github.com/foomo/keel v0.27.1
|
||||
github.com/foomo/opentelemetry-go v0.4.0
|
||||
github.com/nats-io/nats-server/v2 v2.14.3
|
||||
@@ -36,7 +36,7 @@ require (
|
||||
github.com/fatih/color v1.19.0 // indirect
|
||||
github.com/fbiville/markdown-table-formatter v0.3.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/foomo/goflux v0.4.4 // indirect
|
||||
github.com/foomo/goflux v0.6.0 // indirect
|
||||
github.com/foomo/gostandards v0.3.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.10.1 // indirect
|
||||
github.com/go-logr/logr v1.4.4 // indirect
|
||||
@@ -134,6 +134,7 @@ require (
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.54.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20260529124908-c761662dc8c9 // indirect
|
||||
golang.org/x/mod v0.38.0 // indirect
|
||||
golang.org/x/net v0.57.0 // indirect
|
||||
golang.org/x/oauth2 v0.36.0 // indirect
|
||||
golang.org/x/sync v0.22.0 // indirect
|
||||
@@ -144,7 +145,7 @@ require (
|
||||
google.golang.org/genproto v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||
google.golang.org/grpc v1.81.1 // indirect
|
||||
google.golang.org/grpc v1.82.1 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
Generated
+16
-16
@@ -1,5 +1,5 @@
|
||||
charm.land/lipgloss/v2 v2.0.2 h1:xFolbF8JdpNkM2cEPTfXEcW1p6NRzOWTSamRfYEw8cs=
|
||||
charm.land/lipgloss/v2 v2.0.2/go.mod h1:KjPle2Qd3YmvP1KL5OMHiHysGcNwq6u83MUjYkFvEkM=
|
||||
charm.land/lipgloss/v2 v2.0.3 h1:yM2zJ4Cf5Y51b7RHIwioil4ApI/aypFXXVHSwlM6RzU=
|
||||
charm.land/lipgloss/v2 v2.0.3/go.mod h1:7myLU9iG/3xluAWzpY/fSxYYHCgoKTie7laxk6ATwXA=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE=
|
||||
cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU=
|
||||
@@ -36,8 +36,8 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
|
||||
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260330092749-0f94982c930b h1:ASDO9RT6SNKTQN87jO2bRfxHFJq8cgeYdFzivY2gCeM=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260330092749-0f94982c930b/go.mod h1:Vo8TffMf0q7Uho/n8e6XpBZvOWtd3g39yX+9P5rRutA=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260416161146-9c68a866306c h1:a+Q3cOt8vEb6ETG/st32Qjm8R5fdI9wSKb3tqPISnoY=
|
||||
github.com/charmbracelet/ultraviolet v0.0.0-20260416161146-9c68a866306c/go.mod h1:bAAz7dh/FTYfC+oiHavL4mX1tOIBZ0ZwYjSi3qE6ivM=
|
||||
github.com/charmbracelet/x/ansi v0.11.7 h1:kzv1kJvjg2S3r9KHo8hDdHFQLEqn4RBCb39dAYC84jI=
|
||||
github.com/charmbracelet/x/ansi v0.11.7/go.mod h1:9qGpnAVYz+8ACONkZBUWPtL7lulP9No6p1epAihUZwQ=
|
||||
github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk=
|
||||
@@ -76,12 +76,12 @@ github.com/fbiville/markdown-table-formatter v0.3.0 h1:PIm1UNgJrFs8q1htGTw+wnnNY
|
||||
github.com/fbiville/markdown-table-formatter v0.3.0/go.mod h1:q89TDtSEVDdTaufgSbfHpNVdPU/bmfvqNkrC5HagmLY=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/foomo/go v0.14.1 h1:33ePCyAClSj2pqcEI9isyiEe1qoMd6c+Mn0ClLntSoM=
|
||||
github.com/foomo/go v0.14.1/go.mod h1:jeSB/atkoqSoJ3+ak0+b/Xtj7IMyDj1odzJroudT7Dw=
|
||||
github.com/foomo/goflux v0.4.4 h1:T7QhIPdZze3bNEeNjdEAzBV08/ikEgmTmK3maWucAo4=
|
||||
github.com/foomo/goflux v0.4.4/go.mod h1:c2qy02JR9Y5qlVl49nDSEipCQENbGhDZzjT8p72G7Xs=
|
||||
github.com/foomo/gofuncy v0.2.0 h1:fanMIpHocWfoP+u8sevF+Qb/gEh38QeiS6FjeXB+Sx0=
|
||||
github.com/foomo/gofuncy v0.2.0/go.mod h1:WnqsC/Ku/19tk0LYHVG8z9tsT9duKqpxHMiJioznv1M=
|
||||
github.com/foomo/go v0.16.0 h1:Hw2rl0ieMB+s9NK8+MuIHzD22h48whyoKV+CA+lFG1k=
|
||||
github.com/foomo/go v0.16.0/go.mod h1:jeSB/atkoqSoJ3+ak0+b/Xtj7IMyDj1odzJroudT7Dw=
|
||||
github.com/foomo/goflux v0.6.0 h1:O9PYXGevBi2rymxZ+AWm2Kollced45vb4mwz1xWQX1M=
|
||||
github.com/foomo/goflux v0.6.0/go.mod h1:xJZGTK4gZnmiZ5NqcKfTAHtXt9uBB27fRdrH0Voy+jI=
|
||||
github.com/foomo/gofuncy v0.4.0 h1:wxfFOQSp+eZYy9YFXY7A8PPu0n51t4Xhvd6tOm0OSSs=
|
||||
github.com/foomo/gofuncy v0.4.0/go.mod h1:ulEUpkz38K6trv71GM7fHjaUqa/NbWOZUE5MAbfe/Kk=
|
||||
github.com/foomo/gostandards v0.3.0 h1:Ev88Tdu0+52UH/d0l2KcAWx542A13o42d++LSTG0DC4=
|
||||
github.com/foomo/gostandards v0.3.0/go.mod h1:8hJ56tpyFAVwavs5FuUF3po7Bq7hOTkQ1+DzFi4GCWg=
|
||||
github.com/foomo/opentelemetry-go v0.4.0 h1:UQneCUSokIYJXzFUKQSI8rlelbUuf6atgSZMhvD+Nzo=
|
||||
@@ -446,8 +446,8 @@ golang.org/x/exp v0.0.0-20260529124908-c761662dc8c9 h1:4d4PbuBNwaxMXkXI8yiIYjydt
|
||||
golang.org/x/exp v0.0.0-20260529124908-c761662dc8c9/go.mod h1:d2fgXJLVs4dYDHUk5lwMIfzRzSrWCfGZb0ZqeLa/Vcw=
|
||||
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.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
||||
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
||||
golang.org/x/mod v0.38.0 h1:MECBjubtXD7yj4HrhIUcywNaGeNVUdfVnxmPajOk4yk=
|
||||
golang.org/x/mod v0.38.0/go.mod h1:V6Xz0pq8TQ3dGqVQ1FVHuelZpAL0uNhSkk9ogYP3c40=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -505,8 +505,8 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
|
||||
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
|
||||
golang.org/x/tools v0.48.0 h1:3+hClM1aLL5mjMKm5ovokw9epgRXPuu2tILgismM6RE=
|
||||
golang.org/x/tools v0.48.0/go.mod h1:08xX0orndb/F7jJxGDicx061tyd5pcMto75YMAXr6lk=
|
||||
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=
|
||||
@@ -522,8 +522,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.81.1 h1:VnnIIZ88UzOOKLukQi+ImGz8O1Wdp8nAGGnvOfEIWQQ=
|
||||
google.golang.org/grpc v1.81.1/go.mod h1:xGH9GfzOyMTGIOXBJmXt+BX/V0kcdQbdcuwQ/zNw42I=
|
||||
google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE=
|
||||
google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
|
||||
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=
|
||||
|
||||
@@ -5,7 +5,7 @@ go 1.26.0
|
||||
replace github.com/foomo/keel => ../../
|
||||
|
||||
require (
|
||||
github.com/foomo/go v0.14.1
|
||||
github.com/foomo/go v0.16.0
|
||||
github.com/foomo/keel v0.27.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
go.opentelemetry.io/otel v1.44.0
|
||||
|
||||
Generated
+2
-2
@@ -12,8 +12,8 @@ github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yi
|
||||
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA=
|
||||
github.com/fbiville/markdown-table-formatter v0.3.0 h1:PIm1UNgJrFs8q1htGTw+wnnNYvwXQMMMIKNZop2SSho=
|
||||
github.com/fbiville/markdown-table-formatter v0.3.0/go.mod h1:q89TDtSEVDdTaufgSbfHpNVdPU/bmfvqNkrC5HagmLY=
|
||||
github.com/foomo/go v0.14.1 h1:33ePCyAClSj2pqcEI9isyiEe1qoMd6c+Mn0ClLntSoM=
|
||||
github.com/foomo/go v0.14.1/go.mod h1:jeSB/atkoqSoJ3+ak0+b/Xtj7IMyDj1odzJroudT7Dw=
|
||||
github.com/foomo/go v0.16.0 h1:Hw2rl0ieMB+s9NK8+MuIHzD22h48whyoKV+CA+lFG1k=
|
||||
github.com/foomo/go v0.16.0/go.mod h1:jeSB/atkoqSoJ3+ak0+b/Xtj7IMyDj1odzJroudT7Dw=
|
||||
github.com/foomo/opentelemetry-go v0.4.0 h1:UQneCUSokIYJXzFUKQSI8rlelbUuf6atgSZMhvD+Nzo=
|
||||
github.com/foomo/opentelemetry-go v0.4.0/go.mod h1:R3Se/rc5FRAs4ThE6JQ9Oq3cOLo2MOsUzZLJxZquwxA=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
package runtimeutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Caller(skip int) (shortName, fullName, file string, line int, ok bool) { //nolint:nonamedreturns
|
||||
pc, file, line, ok := runtime.Caller(skip + 1)
|
||||
if !ok {
|
||||
return "unknown", "Unknown", "unknown", 0, false
|
||||
}
|
||||
|
||||
fullName = runtime.FuncForPC(pc).Name()
|
||||
|
||||
// Split fullName by last slash to separate package path and the rest
|
||||
lastSlash := strings.LastIndex(fullName, "/")
|
||||
if lastSlash != -1 {
|
||||
return fullName[lastSlash+1:], fullName, file, line, true
|
||||
}
|
||||
|
||||
return fullName, fullName, file, line, true
|
||||
}
|
||||
|
||||
func StackTrace(num, skip int) string {
|
||||
pcs := make([]uintptr, num)
|
||||
n := runtime.Callers(skip+1, pcs)
|
||||
pcs = pcs[:n]
|
||||
|
||||
var ret strings.Builder
|
||||
|
||||
frames := runtime.CallersFrames(pcs)
|
||||
for {
|
||||
frame, more := frames.Next()
|
||||
|
||||
fmt.Fprintf(&ret, "%s\n %s:%d\n", frame.Function, frame.File, frame.Line)
|
||||
|
||||
if !more || len(ret.String()) == num {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return strings.Trim(ret.String(), "\n")
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package runtimeutil_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/foomo/keel/internal/runtimeutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type caller struct{}
|
||||
|
||||
func (c *caller) caller() (string, string, string, int, bool) {
|
||||
return runtimeutil.Caller(0)
|
||||
}
|
||||
|
||||
func TestCaller(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
shortName, fullName, file, line, _ := runtimeutil.Caller(0)
|
||||
|
||||
assert.Equal(t, "runtimeutil_test.TestCaller", shortName)
|
||||
assert.Equal(t, "github.com/foomo/keel/internal/runtimeutil_test.TestCaller", fullName)
|
||||
assert.True(t, strings.HasSuffix(file, "/internal/runtimeutil/caller_test.go"))
|
||||
assert.Equal(t, 21, line)
|
||||
|
||||
c := new(caller)
|
||||
shortName, fullName, file, line, _ = c.caller()
|
||||
|
||||
assert.Equal(t, "runtimeutil_test.(*caller).caller", shortName)
|
||||
assert.Equal(t, "github.com/foomo/keel/internal/runtimeutil_test.(*caller).caller", fullName)
|
||||
assert.True(t, strings.HasSuffix(file, "/internal/runtimeutil/caller_test.go"))
|
||||
assert.Equal(t, 15, line)
|
||||
}
|
||||
|
||||
func TestStackTrace(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
stack := runtimeutil.StackTrace(2, 1)
|
||||
parts := strings.Split(stack, "\n")
|
||||
|
||||
fmt.Println(parts)
|
||||
assert.Len(t, parts, 4)
|
||||
assert.Equal(t, "github.com/foomo/keel/internal/runtimeutil_test.TestStackTrace", parts[0])
|
||||
}
|
||||
+1
-1
@@ -221,7 +221,7 @@ func JobWithOTLPGRCPLogger(enabled bool) JobOption {
|
||||
if config.GetBool(inst.Config(), "otel.enabled", enabled)() {
|
||||
var err error
|
||||
|
||||
inst.loggerProvider, err = telemetry.NewOTLPGRCPLoggerProvider(inst.ctx)
|
||||
inst.loggerProvider, err = telemetry.NewOTLPGRPCLoggerProvider(inst.ctx)
|
||||
log.Must(inst.l, err, "failed to create otlp grpc logger provider")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,18 +4,22 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// Deprecated: use otelhttp
|
||||
func NewHTTPRequestSizeSummaryVec(namespace string) *prometheus.SummaryVec {
|
||||
return NewRequestSizeSummaryVec(namespace, "http", []string{"method", "code"})
|
||||
}
|
||||
|
||||
// Deprecated: use otelhttp
|
||||
func NewHTTPResponseSizeSummaryVec(namespace string) *prometheus.SummaryVec {
|
||||
return NewResponseSizeSummaryVec(namespace, "http", []string{"method", "code"})
|
||||
}
|
||||
|
||||
// Deprecated: use otelhttp
|
||||
func NewHTTPRequestsCounterVec(namespace string) *prometheus.CounterVec {
|
||||
return NewRequestsCounterVec(namespace, "http", []string{"method", "code"})
|
||||
}
|
||||
|
||||
// Deprecated: use otelhttp
|
||||
func NewHTTPRequestDurationHistogram(namespace string) prometheus.Histogram {
|
||||
return NewRequestDurationHistogram(namespace, "http")
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
)
|
||||
|
||||
// Deprecated: will be removed in upcoming releases
|
||||
func Readme() string {
|
||||
md := markdown.Markdown{}
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ go 1.26.0
|
||||
replace github.com/foomo/keel => ../../
|
||||
|
||||
require (
|
||||
github.com/foomo/go v0.14.1
|
||||
github.com/foomo/go v0.16.0
|
||||
github.com/foomo/keel v0.27.1
|
||||
github.com/nats-io/nats.go v1.52.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
|
||||
Generated
+2
-2
@@ -36,8 +36,8 @@ github.com/fbiville/markdown-table-formatter v0.3.0 h1:PIm1UNgJrFs8q1htGTw+wnnNY
|
||||
github.com/fbiville/markdown-table-formatter v0.3.0/go.mod h1:q89TDtSEVDdTaufgSbfHpNVdPU/bmfvqNkrC5HagmLY=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/foomo/go v0.14.1 h1:33ePCyAClSj2pqcEI9isyiEe1qoMd6c+Mn0ClLntSoM=
|
||||
github.com/foomo/go v0.14.1/go.mod h1:jeSB/atkoqSoJ3+ak0+b/Xtj7IMyDj1odzJroudT7Dw=
|
||||
github.com/foomo/go v0.16.0 h1:Hw2rl0ieMB+s9NK8+MuIHzD22h48whyoKV+CA+lFG1k=
|
||||
github.com/foomo/go v0.16.0/go.mod h1:jeSB/atkoqSoJ3+ak0+b/Xtj7IMyDj1odzJroudT7Dw=
|
||||
github.com/foomo/opentelemetry-go v0.4.0 h1:UQneCUSokIYJXzFUKQSI8rlelbUuf6atgSZMhvD+Nzo=
|
||||
github.com/foomo/opentelemetry-go v0.4.0/go.mod h1:R3Se/rc5FRAs4ThE6JQ9Oq3cOLo2MOsUzZLJxZquwxA=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
|
||||
@@ -172,7 +172,7 @@ func WithOTLPGRCPLogger(enabled bool) Option {
|
||||
if config.GetBool(inst.Config(), "otel.enabled", enabled)() {
|
||||
var err error
|
||||
|
||||
inst.loggerProvider, err = telemetry.NewOTLPGRCPLoggerProvider(inst.ctx)
|
||||
inst.loggerProvider, err = telemetry.NewOTLPGRPCLoggerProvider(inst.ctx)
|
||||
log.Must(inst.l, err, "failed to create otlp grpc logger provider")
|
||||
}
|
||||
}
|
||||
@@ -364,6 +364,8 @@ func WithHTTPHealthzService(enabled bool) Option {
|
||||
}
|
||||
|
||||
// WithHTTPReadmeService option with default value
|
||||
//
|
||||
// Deprecated: will be removed in future releases
|
||||
func WithHTTPReadmeService(enabled bool) Option {
|
||||
return func(inst *Server) {
|
||||
if config.GetBool(inst.Config(), "service.readme.enabled", enabled)() {
|
||||
@@ -374,7 +376,7 @@ func WithHTTPReadmeService(enabled bool) Option {
|
||||
}
|
||||
}
|
||||
|
||||
// WithInitService option with default value
|
||||
// WithInitService option with a default value
|
||||
func WithInitService(service Service) Option {
|
||||
return func(inst *Server) {
|
||||
if service == nil || slices.Contains(inst.initServices, service) {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package keelpersistence
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// DistributedRWLock coordinates uploads (shared) against the sync
|
||||
// (exclusive) on one cluster-wide resource. Implemented by
|
||||
// DistributedRWLockMongo; faked in tests. Acquire* return (false, nil)
|
||||
// when blocked by the other side
|
||||
// (no error).
|
||||
type DistributedRWLock interface {
|
||||
AcquireShared(ctx context.Context, lockID string) (bool, error)
|
||||
AcquireExclusive(ctx context.Context, lockID string) (bool, error)
|
||||
Release(ctx context.Context, lockID string) error
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package keelmongo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
mongolock "github.com/foomo/mongo-lock"
|
||||
)
|
||||
|
||||
// DistributedRWLock acquires shared and exclusive locks on one configured resource.
|
||||
type DistributedRWLock struct {
|
||||
client *mongolock.Client
|
||||
resourceName string
|
||||
sharedTTL uint
|
||||
exclusiveTTL uint
|
||||
drainWait time.Duration
|
||||
drainTimeout time.Duration
|
||||
}
|
||||
|
||||
// NewDistributedRWLock builds the lock on the configured collection of persistor and ensures its
|
||||
// indexes exist.
|
||||
func NewDistributedRWLock(persistor *Persistor, cfg DistributedRWLockConfig) (*DistributedRWLock, error) {
|
||||
cfg, err := cfg.normalized()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
col, err := persistor.Collection(cfg.CollectionName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("distributedreadwritelock: collection: %w", err)
|
||||
}
|
||||
|
||||
return &DistributedRWLock{
|
||||
client: mongolock.NewClient(col.Col()),
|
||||
resourceName: cfg.ResourceName,
|
||||
sharedTTL: uint(cfg.SharedTTL.Seconds()),
|
||||
exclusiveTTL: uint(cfg.ExclusiveTTL.Seconds()),
|
||||
drainWait: cfg.DrainWait,
|
||||
drainTimeout: cfg.DrainTimeout,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (l *DistributedRWLock) CreateIndexes(ctx context.Context) error {
|
||||
return l.client.CreateIndexes(ctx)
|
||||
}
|
||||
|
||||
// AcquireShared takes a shared lock. It returns (false, nil) when the exclusive
|
||||
// lock is held — the caller should reject the request — and (true, nil) on
|
||||
// success. Multiple shared holders are allowed concurrently.
|
||||
func (l *DistributedRWLock) AcquireShared(ctx context.Context, lockID string) (bool, error) {
|
||||
err := l.client.SLock(ctx, l.resourceName, lockID, mongolock.LockDetails{TTL: l.sharedTTL}, -1)
|
||||
|
||||
switch {
|
||||
case err == nil:
|
||||
return true, nil
|
||||
case errors.Is(err, mongolock.ErrAlreadyLocked):
|
||||
return false, nil
|
||||
default:
|
||||
return false, fmt.Errorf("distributedreadwritelock: shared: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// AcquireExclusive takes the exclusive lock. It retries for up to DrainTimeout to
|
||||
// let in-flight shared locks drain, then returns (false, nil) if still blocked so
|
||||
// the caller skips this round.
|
||||
func (l *DistributedRWLock) AcquireExclusive(ctx context.Context, lockID string) (bool, error) {
|
||||
deadline := time.Now().Add(l.drainTimeout)
|
||||
|
||||
for {
|
||||
err := l.client.XLock(ctx, l.resourceName, lockID, mongolock.LockDetails{TTL: l.exclusiveTTL})
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if !errors.Is(err, mongolock.ErrAlreadyLocked) {
|
||||
return false, fmt.Errorf("distributedreadwritelock: exclusive: %w", err)
|
||||
}
|
||||
|
||||
if time.Now().After(deadline) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return false, ctx.Err()
|
||||
case <-time.After(l.drainWait):
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Release releases the lock held under lockID (shared or exclusive).
|
||||
func (l *DistributedRWLock) Release(ctx context.Context, lockID string) error {
|
||||
if _, err := l.client.Unlock(ctx, lockID); err != nil {
|
||||
return fmt.Errorf("distributedreadwritelock: unlock: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package keelmongo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// defaultDistributedRWLockExclusiveTTL auto-releases an exclusive lock if the holder crashes
|
||||
// mid-run. It must exceed the holder's run timeout.
|
||||
defaultDistributedRWLockExclusiveTTL = 15 * time.Minute
|
||||
// defaultDistributedRWLockSharedTTL auto-releases a shared lock if the holder dies mid-flight.
|
||||
// Generous, since a shared holder's work can take a while.
|
||||
defaultDistributedRWLockSharedTTL = 10 * time.Minute
|
||||
// defaultDistributedRWLockDrainWait/defaultDrainTimeout bound how long AcquireExclusive retries
|
||||
// to let in-flight shared locks drain before giving up for this round.
|
||||
defaultDistributedRWLockDrainWait = 1 * time.Second
|
||||
// defaultDistributedRWLockDrainTimeout bounds the maximum time AcquireExclusive retries for shared locks to drain.
|
||||
defaultDistributedRWLockDrainTimeout = 60 * time.Second
|
||||
)
|
||||
|
||||
// DistributedRWLockConfig configures a coordinated shared/exclusive lock. CollectionName and
|
||||
// ResourceName are required; the durations and TTLs fall back to defaults when
|
||||
// left at their zero value.
|
||||
type DistributedRWLockConfig struct {
|
||||
// CollectionName is the dedicated Mongo collection holding the lock documents.
|
||||
CollectionName string
|
||||
// ResourceName is the single resource shared and exclusive holders contend on.
|
||||
ResourceName string
|
||||
// ExclusiveTTL auto-releases the exclusive lock if its holder crashes; it must
|
||||
// exceed the holder's run timeout. Defaults to 15m.
|
||||
ExclusiveTTL time.Duration
|
||||
// SharedTTL auto-releases a shared lock if its holder dies mid-flight.
|
||||
// Defaults to 10m.
|
||||
SharedTTL time.Duration
|
||||
// DrainWait is the retry interval while AcquireExclusive waits for in-flight
|
||||
// shared holders to drain. Defaults to 1s.
|
||||
DrainWait time.Duration
|
||||
// DrainTimeout bounds how long AcquireExclusive retries before giving up for
|
||||
// this round. Defaults to 60s.
|
||||
DrainTimeout time.Duration
|
||||
}
|
||||
|
||||
// normalized validates required identifiers and fills unset durations/TTLs with
|
||||
// their defaults, returning the completed config.
|
||||
func (c DistributedRWLockConfig) normalized() (DistributedRWLockConfig, error) {
|
||||
if c.CollectionName == "" {
|
||||
return DistributedRWLockConfig{}, errors.New("distributedreadwritelock: CollectionName is required")
|
||||
}
|
||||
|
||||
if c.ResourceName == "" {
|
||||
return DistributedRWLockConfig{}, errors.New("distributedreadwritelock: ResourceName is required")
|
||||
}
|
||||
|
||||
if c.ExclusiveTTL <= 0 {
|
||||
c.ExclusiveTTL = defaultDistributedRWLockExclusiveTTL
|
||||
}
|
||||
|
||||
if c.SharedTTL <= 0 {
|
||||
c.SharedTTL = defaultDistributedRWLockSharedTTL
|
||||
}
|
||||
|
||||
if c.DrainWait <= 0 {
|
||||
c.DrainWait = defaultDistributedRWLockDrainWait
|
||||
}
|
||||
|
||||
if c.DrainTimeout <= 0 {
|
||||
c.DrainTimeout = defaultDistributedRWLockDrainTimeout
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ replace github.com/foomo/keel => ../../
|
||||
|
||||
require (
|
||||
github.com/foomo/keel v0.27.1
|
||||
github.com/foomo/mongo-lock v0.2.0
|
||||
github.com/go-logr/zapr v1.3.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
go.mongodb.org/mongo-driver/v2 v2.8.0
|
||||
|
||||
Generated
+80
@@ -1,9 +1,39 @@
|
||||
dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8=
|
||||
dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
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/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
|
||||
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
|
||||
github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
|
||||
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94=
|
||||
github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/ebitengine/purego v0.10.1 h1:dewVBCBT2GaMu1SrNTYxQhgQBethzfhiwvZiLGP/qyY=
|
||||
github.com/ebitengine/purego v0.10.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
|
||||
github.com/fbiville/markdown-table-formatter v0.3.0 h1:PIm1UNgJrFs8q1htGTw+wnnNYvwXQMMMIKNZop2SSho=
|
||||
github.com/fbiville/markdown-table-formatter v0.3.0/go.mod h1:q89TDtSEVDdTaufgSbfHpNVdPU/bmfvqNkrC5HagmLY=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/foomo/mongo-lock v0.2.0 h1:xURP2FijZ/feACB5YL1UKUXk23M+x5L+yltEK+sJm0g=
|
||||
github.com/foomo/mongo-lock v0.2.0/go.mod h1:5LMCz8IeaTMCWcgh+aPoDeIjY1qpu8MXbx+FNrGAUFA=
|
||||
github.com/foomo/opentelemetry-go v0.4.0 h1:UQneCUSokIYJXzFUKQSI8rlelbUuf6atgSZMhvD+Nzo=
|
||||
github.com/foomo/opentelemetry-go v0.4.0/go.mod h1:R3Se/rc5FRAs4ThE6JQ9Oq3cOLo2MOsUzZLJxZquwxA=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
@@ -13,18 +43,62 @@ 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-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ=
|
||||
github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/go-test/deep v1.1.1 h1:0r/53hagsehfO4bzD2Pgr/+RgHqhmf+k1Bpse2cTu1U=
|
||||
github.com/go-test/deep v1.1.1/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk=
|
||||
github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||
github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e h1:Q6MvJtQK/iRcRtzAscm/zF23XxJlbECiGPyRicsX+Ak=
|
||||
github.com/lufia/plan9stats v0.0.0-20260330125221-c963978e514e/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
||||
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
|
||||
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/go-archive v0.2.0 h1:zg5QDUM2mi0JIM9fdQZWC7U8+2ZfixfTYoHL7rWUcP8=
|
||||
github.com/moby/go-archive v0.2.0/go.mod h1:mNeivT14o8xU+5q1YnNrkQVpK+dnNe/K6fHqnTg4qPU=
|
||||
github.com/moby/moby/api v1.54.2 h1:wiat9QAhnDQjA7wk1kh/TqHz2I1uUA7M7t9SAl/JNXg=
|
||||
github.com/moby/moby/api v1.54.2/go.mod h1:+RQ6wluLwtYaTd1WnPLykIDPekkuyD/ROWQClE83pzs=
|
||||
github.com/moby/moby/client v0.4.0 h1:S+2XegzHQrrvTCvF6s5HFzcrywWQmuVnhOXe2kiWjIw=
|
||||
github.com/moby/moby/client v0.4.0/go.mod h1:QWPbvWchQbxBNdaLSpoKpCdf5E+WxFAgNHogCWDoa7g=
|
||||
github.com/moby/patternmatcher v0.6.1 h1:qlhtafmr6kgMIJjKJMDmMWq7WLkKIo23hsrpR3x084U=
|
||||
github.com/moby/patternmatcher v0.6.1/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
||||
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
|
||||
github.com/moby/sys/user v0.4.0 h1:jhcMKit7SA80hivmFJcbB1vqmw//wU61Zdui2eQXuMs=
|
||||
github.com/moby/sys/user v0.4.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
||||
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
|
||||
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040=
|
||||
github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/shirou/gopsutil/v4 v4.26.5 h1:RPcBXkpz7kOj9PqGFQOlBPZHsyaPvPVQc098y9RmCNM=
|
||||
github.com/shirou/gopsutil/v4 v4.26.5/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ=
|
||||
github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
||||
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/testcontainers/testcontainers-go v0.43.0 h1:oEQx5MW2DGd9z3AeEQfB2lPM0eLs7ztyaGRu75bFo5A=
|
||||
github.com/testcontainers/testcontainers-go v0.43.0/go.mod h1:+VxkT2NQnKOZPKi6praMuMKYHYyOGXr0XSBSlSMCzFo=
|
||||
github.com/testcontainers/testcontainers-go/modules/mongodb v0.43.0 h1:RJlAAz8dv61icyHvFmrr1xZHJEWZdvBfVBAU6wnmGPM=
|
||||
github.com/testcontainers/testcontainers-go/modules/mongodb v0.43.0/go.mod h1:1zaDEZyV1SK+mpz83tmB2KthF6DHaS4Y+lRvy3d2XiE=
|
||||
github.com/tklauser/go-sysconf v0.4.0 h1:7H0uAN+7RkwWRaxhYXDLqa5V3LPrJeV8wmD9dRUgPQU=
|
||||
github.com/tklauser/go-sysconf v0.4.0/go.mod h1:8mTNWyog7H+MpKijp4VmKJAd2bbYQ2zuUwkYRbUArPI=
|
||||
github.com/tklauser/numcpus v0.12.0 h1:NR85qdvHA9pFse3x3weVZ0r0ST8R6l5RHbZrlRaqob4=
|
||||
github.com/tklauser/numcpus v0.12.0/go.mod h1:ABHeXzJnr/qqwguhClkZKT1/8VABcYrsyUiUGobwWJg=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.2.0 h1:bYKF2AEwG5rqd1BumT4gAnvwU/M9nBp2pTSxeZw7Wvs=
|
||||
@@ -34,12 +108,16 @@ github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gi
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.mongodb.org/mongo-driver/v2 v2.8.0 h1:CxWDGQYY8QQwNjAl/aq2sfWakdnWZynnqJ9F4DhHbP8=
|
||||
go.mongodb.org/mongo-driver/v2 v2.8.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo v0.0.0-20260623174712-bbae83b5df0c h1:etHDCLakSn0jdNgLzYZ0zGKiwaNMof0R/uA+hVqIXQo=
|
||||
go.opentelemetry.io/contrib/instrumentation/go.mongodb.org/mongo-driver/v2/mongo/otelmongo v0.0.0-20260623174712-bbae83b5df0c/go.mod h1:VgtIsrVXKo8KmG2sFvQazHcQ98P2FHQ+ZePXtpTPjqs=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0 h1:8tvICD4vSTOOsNrsI4Ljf6C+6UKvpTEH5XY3JMoyPoo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.69.0/go.mod h1:z9+yiacE0IHRqM4qFfkbt/JYlmYXgss8GY/jXoNuPJI=
|
||||
go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU=
|
||||
go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc=
|
||||
go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc=
|
||||
@@ -91,3 +169,5 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
|
||||
gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package semconv
|
||||
|
||||
import (
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
const (
|
||||
// DebugEnabledKey is the key for debug.enabled.
|
||||
DebugEnabledKey = attribute.Key("debug.enabled")
|
||||
)
|
||||
|
||||
// DebugEnabled returns a new attribute.KeyValue for keel.service.type.
|
||||
func DebugEnabled(v bool) attribute.KeyValue {
|
||||
return DebugEnabledKey.Bool(v)
|
||||
}
|
||||
@@ -149,6 +149,7 @@ func NewServer(opts ...Option) *Server {
|
||||
|
||||
// add probe
|
||||
inst.AddAlwaysHealthzers(inst)
|
||||
//nolint:staticcheck //SA1019
|
||||
inst.AddReadmers(
|
||||
interfaces.ReadmeFunc(env.Readme),
|
||||
interfaces.ReadmeFunc(config.Readme),
|
||||
@@ -251,11 +252,15 @@ func (s *Server) AddClosers(closers ...any) {
|
||||
}
|
||||
|
||||
// AddReadmer adds a readmer to be added to the exposed readme
|
||||
//
|
||||
// Deprecated: will be removed in future releases
|
||||
func (s *Server) AddReadmer(readmer interfaces.Readmer) {
|
||||
s.addReadmers(readmer)
|
||||
}
|
||||
|
||||
// AddReadmers adds readmers to be added to the exposed readme
|
||||
//
|
||||
// Deprecated: will be removed in future releases
|
||||
func (s *Server) AddReadmers(readmers ...interfaces.Readmer) {
|
||||
for _, readmer := range readmers {
|
||||
s.AddReadmer(readmer)
|
||||
|
||||
@@ -56,7 +56,7 @@ func NewGoRoutine(l *zap.Logger, name string, handler GoRoutineFn, opts ...GoRou
|
||||
// ~ Options
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func GoRoutineWithPralllel(v int) GoRoutineOption {
|
||||
func GoRoutineWithParallel(v int) GoRoutineOption {
|
||||
return func(o *GoRoutine) {
|
||||
o.parallel = v
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ func ExampleNewGoRoutine() {
|
||||
for {
|
||||
// handle graceful shutdowns
|
||||
if err := ctx.Err(); errors.Is(context.Cause(ctx), service.ErrServiceShutdown) {
|
||||
l.Info("context has been canceled du to graceful shutdow")
|
||||
l.Info("context has been canceled du to graceful shutdown")
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return errors.Wrap(err, "unexpected context error")
|
||||
@@ -50,7 +50,7 @@ func ExampleNewGoRoutine() {
|
||||
// {"level":"info","msg":"keel closer closed","graceful_period":"3s"}
|
||||
// {"level":"info","msg":"keel closer closed: closers"}
|
||||
// {"level":"info","msg":"stopping keel service","keel_service_type":"goroutine","keel_service_name":"demo"}
|
||||
// {"level":"info","msg":"context has been canceled du to graceful shutdow","keel_service_type":"goroutine","keel_service_name":"demo","keel_service_inst":0}
|
||||
// {"level":"info","msg":"context has been canceled du to graceful shutdown","keel_service_type":"goroutine","keel_service_name":"demo","keel_service_inst":0}
|
||||
// {"level":"debug","msg":"keel closer closed","name":"*service.GoRoutine"}
|
||||
// {"level":"debug","msg":"keel closer closed","name":"noop.TracerProvider"}
|
||||
// {"level":"debug","msg":"keel closer closed","name":"noop.MeterProvider"}
|
||||
|
||||
@@ -14,6 +14,7 @@ var (
|
||||
DefaultHTTPReadmePath = "/readme"
|
||||
)
|
||||
|
||||
// Deprecated: will be removed in upcoming releases
|
||||
func NewHTTPReadme(l *zap.Logger, name, addr, path string, readmers func() []interfaces.Readmer) *HTTP {
|
||||
handler := http.NewServeMux()
|
||||
handler.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -36,6 +37,7 @@ func NewHTTPReadme(l *zap.Logger, name, addr, path string, readmers func() []int
|
||||
return NewHTTP(l, name, addr, handler)
|
||||
}
|
||||
|
||||
// Deprecated: will be removed in upcoming releases
|
||||
func NewDefaultHTTPReadme(l *zap.Logger, readmers func() []interfaces.Readmer) *HTTP {
|
||||
return NewHTTPReadme(
|
||||
l,
|
||||
|
||||
@@ -27,7 +27,7 @@ func _ExampleNewHTTPReadme() {
|
||||
svr := keel.NewServer(
|
||||
keel.WithLogger(zap.NewNop()),
|
||||
keel.WithTelemetry(),
|
||||
keel.WithHTTPReadmeService(true),
|
||||
keel.WithHTTPReadmeService(true), //nolint:staticcheck
|
||||
keel.WithGracefulPeriod(3*time.Second),
|
||||
)
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ func NewLoggerProviderFromEnv(ctx context.Context) (log.LoggerProvider, error) {
|
||||
case exporterOTLP:
|
||||
switch protocol := otlpProtocol("logs"); protocol {
|
||||
case protocolGRPC:
|
||||
return NewOTLPGRCPLoggerProvider(ctx)
|
||||
return NewOTLPGRPCLoggerProvider(ctx)
|
||||
case protocolHTTP:
|
||||
return NewOTLPHTTPLoggerProvider(ctx)
|
||||
default:
|
||||
|
||||
+6
-6
@@ -1,17 +1,17 @@
|
||||
package telemetry
|
||||
|
||||
import (
|
||||
runtimex "github.com/foomo/go/runtime"
|
||||
goruntime "github.com/foomo/go/runtime"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.41.0"
|
||||
)
|
||||
|
||||
func CodeCaller(skip int) []attribute.KeyValue {
|
||||
if shortName, _, file, line, ok := runtimex.Caller(skip + 1); ok {
|
||||
if fr := goruntime.CallFrame(skip + 1); !fr.Zero() {
|
||||
return []attribute.KeyValue{
|
||||
semconv.CodeFunctionName(shortName),
|
||||
semconv.CodeFilePath(file),
|
||||
semconv.CodeLineNumber(line),
|
||||
semconv.CodeFunctionName(fr.Name()),
|
||||
semconv.CodeFilePath(fr.File),
|
||||
semconv.CodeLineNumber(fr.Line),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,5 +19,5 @@ func CodeCaller(skip int) []attribute.KeyValue {
|
||||
}
|
||||
|
||||
func CodeStacktrace(num, skip int) attribute.KeyValue {
|
||||
return semconv.CodeStacktrace(runtimex.StackTrace(num, skip+1))
|
||||
return semconv.CodeStacktrace(goruntime.StackTrace(num, skip+1))
|
||||
}
|
||||
|
||||
+27
-1
@@ -1,6 +1,32 @@
|
||||
package telemetry
|
||||
|
||||
import (
|
||||
"runtime/debug"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
Name = "github.com/foomo/keel"
|
||||
Name = "github.com/foomo/keel/telemetry"
|
||||
DefaultServiceName = "undefined"
|
||||
)
|
||||
|
||||
// Version returns the keel module version for use as the OTel instrumentation
|
||||
// scope version. Resolved once from build info; empty string if unavailable.
|
||||
var Version = sync.OnceValue(func() string {
|
||||
bi, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
if bi.Main.Path == Name {
|
||||
return bi.Main.Version
|
||||
}
|
||||
|
||||
for _, d := range bi.Deps {
|
||||
if d.Path == Name {
|
||||
return d.Version
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
})
|
||||
|
||||
+105
-89
@@ -3,121 +3,165 @@ package telemetry
|
||||
import (
|
||||
"context"
|
||||
"runtime/pprof"
|
||||
"time"
|
||||
|
||||
"github.com/foomo/keel/internal/runtimeutil"
|
||||
foomosemconv "github.com/foomo/opentelemetry-go/semconv"
|
||||
"github.com/grafana/pyroscope-go"
|
||||
"github.com/pkg/errors"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.41.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"go.uber.org/zap/zapcore"
|
||||
)
|
||||
|
||||
type Context struct {
|
||||
context.Context
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
// Ctx returns a new Context from the given context.Context.
|
||||
func Ctx(ctx context.Context) Context {
|
||||
return Context{ctx}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Public methods
|
||||
// ~ Log methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
// LogDebug logs a message at debug level.
|
||||
// LogDebug logs a message at `debug` level.
|
||||
func (c Context) LogDebug(msg string, kv ...attribute.KeyValue) {
|
||||
c.log(c.Context, zapcore.DebugLevel, msg, 1, kv...)
|
||||
Log(c.ctx, zapcore.DebugLevel, msg, 1, kv...)
|
||||
}
|
||||
|
||||
// LogInfo logs a message at info level.
|
||||
// LogInfo logs a message at `info` level.
|
||||
func (c Context) LogInfo(msg string, kv ...attribute.KeyValue) {
|
||||
c.log(c.Context, zapcore.InfoLevel, msg, 1, kv...)
|
||||
Log(c.ctx, zapcore.InfoLevel, msg, 1, kv...)
|
||||
}
|
||||
|
||||
// LogWarn logs a message at warn level.
|
||||
// LogWarn logs a message at `warn` level.
|
||||
func (c Context) LogWarn(msg string, kv ...attribute.KeyValue) {
|
||||
c.log(c.Context, zapcore.WarnLevel, msg, 1, kv...)
|
||||
Log(c.ctx, zapcore.WarnLevel, msg, 1, kv...)
|
||||
}
|
||||
|
||||
// LogError logs a message at error level.
|
||||
// LogError logs a message at `error` level.
|
||||
func (c Context) LogError(msg string, kv ...attribute.KeyValue) {
|
||||
c.log(c.Context, zapcore.ErrorLevel, msg, 1, kv...)
|
||||
Log(c.ctx, zapcore.ErrorLevel, msg, 1, kv...)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Context methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
// Context returns the underlying context.Context.
|
||||
func (c Context) Context() context.Context {
|
||||
return c.ctx
|
||||
}
|
||||
|
||||
// WithCancel returns a copy of the context with a new Done channel.
|
||||
// The returned context's Done channel is closed when the returned cancel function
|
||||
// is called or when the parent context's Done channel is closed, whichever happens first.
|
||||
func (c Context) WithCancel() (context.Context, context.CancelFunc) {
|
||||
return context.WithCancel(c.ctx)
|
||||
}
|
||||
|
||||
// WithCancelCause returns a copy of the context with a new Done channel and
|
||||
// a CancelCauseFunc instead of a CancelFunc. Calling cancel with a non-nil error
|
||||
// (the "cause") records that error in the context; it can then be retrieved using Cause(ctx).
|
||||
func (c Context) WithCancelCause() (context.Context, context.CancelCauseFunc) {
|
||||
return context.WithCancelCause(c.ctx)
|
||||
}
|
||||
|
||||
// WithDeadline returns a copy of the context with a deadline.
|
||||
// The returned context's Done channel is closed when the deadline expires, when the
|
||||
// returned cancel function is called, or when the parent context's Done channel is
|
||||
// closed, whichever happens first.
|
||||
func (c Context) WithDeadline(deadline time.Time) (context.Context, context.CancelFunc) {
|
||||
return context.WithDeadline(c.ctx, deadline)
|
||||
}
|
||||
|
||||
// WithTimeout returns a copy of the context with a timeout.
|
||||
// It is equivalent to ContextWith(time.Now().Add(timeout)).
|
||||
func (c Context) WithTimeout(timeout time.Duration) (context.Context, context.CancelFunc) {
|
||||
return context.WithTimeout(c.ctx, timeout)
|
||||
}
|
||||
|
||||
// WithValue returns a copy of the context with the key-value pair associated.
|
||||
func (c Context) WithValue(key, val any) context.Context {
|
||||
return context.WithValue(c.ctx, key, val)
|
||||
}
|
||||
|
||||
// WithoutCancel returns a copy of the context that is not canceled when
|
||||
// parent is canceled. The returned context returns no Deadline or Err, and its
|
||||
// Done channel is nil.
|
||||
func (c Context) WithoutCancel() context.Context {
|
||||
return context.WithoutCancel(c.ctx)
|
||||
}
|
||||
|
||||
// Value returns the value associated with this context for key, or nil
|
||||
// if no value is associated with key.
|
||||
func (c Context) Value(key any) any {
|
||||
return c.ctx.Value(key)
|
||||
}
|
||||
|
||||
// Deadline returns the time when work done on behalf of this context should be
|
||||
// canceled. Deadline returns ok==false when no deadline is set.
|
||||
func (c Context) Deadline() (deadline time.Time, ok bool) { //nolint:nonamedreturns
|
||||
return c.ctx.Deadline()
|
||||
}
|
||||
|
||||
// Done returns a channel that's closed when work done on behalf of this context
|
||||
// should be canceled. Done may return nil if this context can never be canceled.
|
||||
func (c Context) Done() <-chan struct{} {
|
||||
return c.ctx.Done()
|
||||
}
|
||||
|
||||
// Err returns a non-nil error value after Done is closed. Err returns Canceled
|
||||
// if the context was canceled or DeadlineExceeded if the context's deadline passed.
|
||||
func (c Context) Err() error {
|
||||
return c.ctx.Err()
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Trace methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
// Span returns the span from the context.
|
||||
func (c Context) Span() trace.Span {
|
||||
return trace.SpanFromContext(c.Context)
|
||||
return SpanFromContext(c.ctx)
|
||||
}
|
||||
|
||||
// SetSpanDebug sets the span debug attribute.
|
||||
func (c Context) SetSpanDebug() {
|
||||
c.Span().SetAttributes(attribute.Bool("debug.enabled", true))
|
||||
SetSpanDebug(c.ctx)
|
||||
}
|
||||
|
||||
// EndSpan ends the span.
|
||||
func (c Context) EndSpan(err error, opts ...trace.SpanEndOption) {
|
||||
sp := c.Span()
|
||||
if sp.IsRecording() {
|
||||
if err != nil {
|
||||
sp.RecordError(err, trace.WithAttributes(semconv.CodeStacktrace(runtimeutil.StackTrace(3, 1))))
|
||||
sp.SetStatus(codes.Error, errors.Cause(err).Error())
|
||||
} else {
|
||||
c.SetSpanStatusOK()
|
||||
}
|
||||
|
||||
sp.End(opts...)
|
||||
}
|
||||
EndSpan(c.ctx, err, opts...)
|
||||
}
|
||||
|
||||
// DeferEndSpan is a helper so you can do `defer ctx.DeferEndSpan(&err)` instead of `defer func(){ ctx.EndSpan(err) }()`
|
||||
// DeferEndSpan is a helper, so you can do `defer ctx.DeferEndSpan(&err)` instead of `defer func(){ ctx.EndSpan(err) }()`
|
||||
func (c Context) DeferEndSpan(err *error, opts ...trace.SpanEndOption) {
|
||||
e := *err
|
||||
|
||||
sp := c.Span()
|
||||
if sp.IsRecording() {
|
||||
if e != nil {
|
||||
sp.RecordError(e, trace.WithAttributes(CodeStacktrace(5, 2)))
|
||||
sp.SetStatus(codes.Error, errors.Cause(e).Error())
|
||||
} else {
|
||||
c.SetSpanStatusOK()
|
||||
}
|
||||
|
||||
sp.End(opts...)
|
||||
}
|
||||
DeferEndSpan(c.ctx, err, opts...)
|
||||
}
|
||||
|
||||
// SetSpanStatusOK sets the status of the span to ok.
|
||||
func (c Context) SetSpanStatusOK() {
|
||||
sp := c.Span()
|
||||
if sp.IsRecording() {
|
||||
sp.SetStatus(codes.Ok, "")
|
||||
}
|
||||
c.Span().SetStatus(codes.Ok, "")
|
||||
}
|
||||
|
||||
// SetSpanStatusError sets the status of the span to error.
|
||||
func (c Context) SetSpanStatusError(description string) {
|
||||
sp := c.Span()
|
||||
if sp.IsRecording() {
|
||||
sp.SetStatus(codes.Error, description)
|
||||
}
|
||||
c.Span().SetStatus(codes.Error, description)
|
||||
}
|
||||
|
||||
// SetSpanName sets the name of the span.
|
||||
func (c Context) SetSpanName(name string) {
|
||||
sp := c.Span()
|
||||
if sp.IsRecording() {
|
||||
sp.SetName(name)
|
||||
}
|
||||
c.Span().SetName(name)
|
||||
}
|
||||
|
||||
// SetSpanAttributes sets the attributes of the span.
|
||||
func (c Context) SetSpanAttributes(kv ...attribute.KeyValue) {
|
||||
sp := c.Span()
|
||||
if sp.IsRecording() {
|
||||
sp.SetAttributes(kv...)
|
||||
}
|
||||
c.Span().SetAttributes(kv...)
|
||||
}
|
||||
|
||||
// RecordError records an error on the span and logs it.
|
||||
@@ -144,27 +188,24 @@ func (c Context) RecordSpanError(err error, kv ...attribute.KeyValue) {
|
||||
|
||||
// AddSpanEvent adds an event to the span.
|
||||
func (c Context) AddSpanEvent(name string, kv ...attribute.KeyValue) {
|
||||
sp := c.Span()
|
||||
if sp.IsRecording() {
|
||||
sp.AddEvent(name, trace.WithAttributes(kv...))
|
||||
}
|
||||
c.Span().AddEvent(name, trace.WithAttributes(kv...))
|
||||
}
|
||||
|
||||
// StartSpan starts a span.
|
||||
func (c Context) StartSpan(opts ...trace.SpanStartOption) Context {
|
||||
ctx, _ := c.startSpan("FUNC", 1, opts...)
|
||||
ctx, _ := startSpan(c.ctx, 1, opts...)
|
||||
return ctx
|
||||
}
|
||||
|
||||
// StartSpanWithNewRoot sets the name of the span.
|
||||
func (c Context) StartSpanWithNewRoot(opts ...trace.SpanStartOption) Context {
|
||||
ctx, _ := c.startSpan("FUNC", 1, append(opts, trace.WithNewRoot(), trace.WithLinks(trace.LinkFromContext(c.Context)))...)
|
||||
ctx, _ := startSpan(c.ctx, 1, append(opts, trace.WithNewRoot(), trace.WithLinks(trace.LinkFromContext(c.ctx)))...)
|
||||
return ctx
|
||||
}
|
||||
|
||||
// StartSpanWithProfile starts a span and profiles the handler.
|
||||
func (c Context) StartSpanWithProfile(name string, handler func(ctx Context), kv ...attribute.KeyValue) {
|
||||
ctx, span := c.startSpan("FUNC", 1, trace.WithAttributes(kv...))
|
||||
ctx, span := startSpan(c.ctx, 1, trace.WithAttributes(kv...))
|
||||
defer span.End()
|
||||
|
||||
ctx.StartProfile(name, handler, kv...)
|
||||
@@ -174,40 +215,15 @@ func (c Context) StartSpanWithProfile(name string, handler func(ctx Context), kv
|
||||
func (c Context) StartProfile(name string, handler func(ctx Context), kv ...attribute.KeyValue) {
|
||||
attr := foomosemconv.ProfileName(name)
|
||||
c.Span().SetAttributes(attr)
|
||||
pyroscope.TagWrapper(c.Context, PyroscopeLabels(append(kv, attr)...), func(ctx context.Context) {
|
||||
pyroscope.TagWrapper(c.ctx, PyroscopeLabels(append(kv, attr)...), func(ctx context.Context) {
|
||||
handler(Ctx(ctx))
|
||||
})
|
||||
}
|
||||
|
||||
// SetProfileAttributes sets the labels for the profile.
|
||||
func (c Context) SetProfileAttributes(kv ...attribute.KeyValue) Context {
|
||||
ctx := pprof.WithLabels(c.Context, PyroscopeLabels(kv...))
|
||||
ctx := pprof.WithLabels(c.ctx, PyroscopeLabels(kv...))
|
||||
pprof.SetGoroutineLabels(ctx)
|
||||
|
||||
return Ctx(ctx)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// ~ Private methods
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
func (c Context) startSpan(prefix string, skip int, opts ...trace.SpanStartOption) (Context, trace.Span) {
|
||||
name := prefix
|
||||
|
||||
if shortName, _, file, line, ok := runtimeutil.Caller(skip + 1); ok {
|
||||
name += " " + shortName
|
||||
opts = append(opts, trace.WithAttributes(
|
||||
semconv.CodeFunctionName(shortName),
|
||||
semconv.CodeLineNumber(line),
|
||||
semconv.CodeFilePath(file),
|
||||
))
|
||||
}
|
||||
|
||||
ctx, span := Tracer().Start(c.Context, name, opts...) //nolint:spancheck
|
||||
|
||||
return Ctx(ctx), span //nolint:spancheck
|
||||
}
|
||||
|
||||
func (c Context) log(ctx context.Context, lvl zapcore.Level, msg string, skip int, kv ...attribute.KeyValue) {
|
||||
Log(ctx, lvl, msg, skip+1, kv...)
|
||||
}
|
||||
|
||||
@@ -53,20 +53,6 @@ func TestCtx(t *testing.T) {
|
||||
require.Len(t, spanRecorder.Ended(), 1)
|
||||
})
|
||||
|
||||
t.Run("EndSpan Ok", func(t *testing.T) {
|
||||
spanRecorder.Reset()
|
||||
|
||||
ctx := telemetry.Ctx(t.Context()).StartSpan()
|
||||
require.Len(t, spanRecorder.Started(), 1)
|
||||
ctx.EndSpan(nil)
|
||||
// repeat
|
||||
ctx.EndSpan(errors.New("error"))
|
||||
|
||||
spans := spanRecorder.Ended()
|
||||
require.Len(t, spans, 1)
|
||||
assert.Equal(t, codes.Ok, spans[0].Status().Code)
|
||||
})
|
||||
|
||||
t.Run("EndSpan Error", func(t *testing.T) {
|
||||
spanRecorder.Reset()
|
||||
|
||||
|
||||
+10
-1
@@ -2,10 +2,13 @@ package telemetry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
|
||||
goruntime "github.com/foomo/go/runtime"
|
||||
"github.com/foomo/keel/log"
|
||||
foomosemconv "github.com/foomo/opentelemetry-go/semconv"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.41.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
@@ -42,7 +45,13 @@ func Log(ctx context.Context, lvl zapcore.Level, msg string, skip int, kv ...att
|
||||
)
|
||||
}
|
||||
|
||||
attrs = append(attrs, CodeCaller(skip+1)...)
|
||||
if fr := goruntime.CallFrame(skip + 1); !fr.Zero() {
|
||||
attrs = append(attrs,
|
||||
semconv.CodeFunctionName(fr.Short()),
|
||||
semconv.CodeFilePath(path.Join(path.Base(path.Dir(fr.File)), path.Base(fr.File))),
|
||||
semconv.CodeLineNumber(fr.Line),
|
||||
)
|
||||
}
|
||||
|
||||
zap.L().WithOptions(zap.WithCaller(false)).Log(lvl, msg, log.Attributes(attrs...)...)
|
||||
}
|
||||
|
||||
@@ -75,8 +75,8 @@ func NewOTLPHTTPLoggerProvider(ctx context.Context) (log.LoggerProvider, error)
|
||||
return newLoggerProvider(ctx, sdklog.NewBatchProcessor(exp))
|
||||
}
|
||||
|
||||
// NewOTLPGRCPLoggerProvider creates a new OTLP gRPC-based logger provider using the provided context.
|
||||
func NewOTLPGRCPLoggerProvider(ctx context.Context) (log.LoggerProvider, error) {
|
||||
// NewOTLPGRPCLoggerProvider creates a new OTLP gRPC-based logger provider using the provided context.
|
||||
func NewOTLPGRPCLoggerProvider(ctx context.Context) (log.LoggerProvider, error) {
|
||||
exp, err := otlploggrpc.New(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -85,6 +85,11 @@ func NewOTLPGRCPLoggerProvider(ctx context.Context) (log.LoggerProvider, error)
|
||||
return newLoggerProvider(ctx, sdklog.NewBatchProcessor(exp))
|
||||
}
|
||||
|
||||
// Deprecated: use NewOTLPGRPCLoggerProvider (this was a misspelling).
|
||||
func NewOTLPGRCPLoggerProvider(ctx context.Context) (log.LoggerProvider, error) {
|
||||
return NewOTLPGRPCLoggerProvider(ctx)
|
||||
}
|
||||
|
||||
func newLoggerProvider(ctx context.Context, p sdklog.Processor) (log.LoggerProvider, error) {
|
||||
resource, err := NewResource(ctx)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
package telemetry_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"go.uber.org/goleak"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
goleak.VerifyTestMain(m,
|
||||
goleak.IgnoreTopFunction("go.opentelemetry.io/otel/sdk/metric.(*PeriodicReader).run"),
|
||||
goleak.IgnoreTopFunction("go.opentelemetry.io/otel/sdk/trace.(*batchSpanProcessor).processQueue"),
|
||||
)
|
||||
}
|
||||
+3
-1
@@ -5,6 +5,8 @@ import (
|
||||
)
|
||||
|
||||
// Meter returns a metric.Meter instance with the provided options, using the default MeterProvider and the defined Name.
|
||||
// The instrumentation scope version defaults to the keel module version; pass a
|
||||
// metric.WithInstrumentationVersion option to override it.
|
||||
func Meter(opts ...metric.MeterOption) metric.Meter {
|
||||
return MeterProvider().Meter(Name, opts...)
|
||||
return MeterProvider().Meter(Name, append([]metric.MeterOption{metric.WithInstrumentationVersion(Version())}, opts...)...)
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func MeterProvider() metric.MeterProvider {
|
||||
return otel.GetMeterProvider()
|
||||
}
|
||||
|
||||
// NewNoopMeterProvider returns a no-op metric.MeterProvider and sets it as the global MeterProvider.
|
||||
// NewNoopMeterProvider returns a no-op metric.MeterProvider.
|
||||
func NewNoopMeterProvider() metric.MeterProvider {
|
||||
return noop.NewMeterProvider()
|
||||
}
|
||||
@@ -36,7 +36,7 @@ func NewStdOutMeterProvider(ctx context.Context, opts ...stdoutmetric.Option) (m
|
||||
opts = append(opts, stdoutmetric.WithEncoder(enc))
|
||||
}
|
||||
|
||||
if !env.GetBool("OTEL_EXPORTER_STDOUT_TIMESTAMP", true) {
|
||||
if !env.GetBool("OTEL_EXPORTER_STDOUT_TIMESTAMPS", true) {
|
||||
opts = append(opts, stdoutmetric.WithoutTimestamps())
|
||||
}
|
||||
|
||||
|
||||
+30
-166
@@ -1,36 +1,14 @@
|
||||
package telemetry
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
foomosemconv "github.com/foomo/opentelemetry-go/semconv"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"go.opentelemetry.io/otel/metric/noop"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.41.0"
|
||||
)
|
||||
|
||||
// NewIntHistogram creates and returns a Int64Histogram metric instrument with the specified name and optional settings.
|
||||
func NewIntHistogram(name string, opts ...any) metric.Int64Histogram {
|
||||
var (
|
||||
meterOptions []metric.MeterOption
|
||||
metricOptions []metric.Int64HistogramOption
|
||||
)
|
||||
|
||||
for _, v := range opts {
|
||||
switch t := v.(type) {
|
||||
case metric.MeterOption:
|
||||
meterOptions = append(meterOptions, t)
|
||||
case metric.HistogramOption:
|
||||
metricOptions = append(metricOptions, t)
|
||||
case metric.Int64HistogramOption:
|
||||
metricOptions = append(metricOptions, t)
|
||||
default:
|
||||
Ctx(context.TODO()).LogWarn("invalid Histogram option", foomosemconv.ReflectType(v))
|
||||
}
|
||||
}
|
||||
|
||||
m, err := Meter(meterOptions...).Int64Histogram(name, metricOptions...)
|
||||
// NewIntHistogram creates and returns a Int64Histogram metric instrument with the specified name and options.
|
||||
func NewIntHistogram(name string, opts ...metric.Int64HistogramOption) metric.Int64Histogram {
|
||||
m, err := Meter().Int64Histogram(name, opts...)
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
return noop.Int64Histogram{}
|
||||
@@ -39,27 +17,9 @@ func NewIntHistogram(name string, opts ...any) metric.Int64Histogram {
|
||||
return m
|
||||
}
|
||||
|
||||
// NewFloatHistogram creates and returns a Float64Histogram metric instrument with the specified name and optional settings.
|
||||
func NewFloatHistogram(name string, opts ...any) metric.Float64Histogram {
|
||||
var (
|
||||
meterOptions []metric.MeterOption
|
||||
metricOptions []metric.Float64HistogramOption
|
||||
)
|
||||
|
||||
for _, v := range opts {
|
||||
switch t := v.(type) {
|
||||
case metric.MeterOption:
|
||||
meterOptions = append(meterOptions, t)
|
||||
case metric.HistogramOption:
|
||||
metricOptions = append(metricOptions, t)
|
||||
case metric.Float64HistogramOption:
|
||||
metricOptions = append(metricOptions, t)
|
||||
default:
|
||||
Ctx(context.TODO()).LogWarn("invalid Histogram option", foomosemconv.ReflectType(v))
|
||||
}
|
||||
}
|
||||
|
||||
m, err := Meter(meterOptions...).Float64Histogram(name, metricOptions...)
|
||||
// NewFloatHistogram creates and returns a Float64Histogram metric instrument with the specified name and options.
|
||||
func NewFloatHistogram(name string, opts ...metric.Float64HistogramOption) metric.Float64Histogram {
|
||||
m, err := Meter().Float64Histogram(name, opts...)
|
||||
if err != nil {
|
||||
otel.Handle(err)
|
||||
return noop.Float64Histogram{}
|
||||
@@ -68,162 +28,66 @@ func NewFloatHistogram(name string, opts ...any) metric.Float64Histogram {
|
||||
return m
|
||||
}
|
||||
|
||||
// NewIntGauge creates and returns a Int64Gauge metric instrument with the specified name and optional settings.
|
||||
func NewIntGauge(name string, opts ...any) metric.Int64Gauge {
|
||||
var (
|
||||
meterOptions []metric.MeterOption
|
||||
metricOptions []metric.Int64GaugeOption
|
||||
)
|
||||
|
||||
for _, v := range opts {
|
||||
switch t := v.(type) {
|
||||
case metric.MeterOption:
|
||||
meterOptions = append(meterOptions, t)
|
||||
case metric.Int64GaugeOption:
|
||||
metricOptions = append(metricOptions, t)
|
||||
default:
|
||||
Ctx(context.TODO()).LogWarn("invalid Gauge option", foomosemconv.ReflectType(v))
|
||||
}
|
||||
}
|
||||
|
||||
m, err := Meter(meterOptions...).Int64Gauge(name, metricOptions...)
|
||||
// NewIntGauge creates and returns a Int64Gauge metric instrument with the specified name and options.
|
||||
func NewIntGauge(name string, opts ...metric.Int64GaugeOption) metric.Int64Gauge {
|
||||
m, err := Meter().Int64Gauge(name, opts...)
|
||||
if err != nil {
|
||||
Ctx(context.TODO()).LogWarn("failed to create Gauge", semconv.ErrorType(err), semconv.ExceptionMessage(err.Error()))
|
||||
otel.Handle(err)
|
||||
return noop.Int64Gauge{}
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// NewFloatGauge creates and returns a Float64Gauge metric with the specified name and optional configurations.
|
||||
func NewFloatGauge(name string, opts ...any) metric.Float64Gauge {
|
||||
var (
|
||||
meterOptions []metric.MeterOption
|
||||
metricOptions []metric.Float64GaugeOption
|
||||
)
|
||||
|
||||
for _, v := range opts {
|
||||
switch t := v.(type) {
|
||||
case metric.MeterOption:
|
||||
meterOptions = append(meterOptions, t)
|
||||
case metric.Float64GaugeOption:
|
||||
metricOptions = append(metricOptions, t)
|
||||
default:
|
||||
Ctx(context.TODO()).LogWarn("invalid Gauge option", foomosemconv.ReflectType(v))
|
||||
}
|
||||
}
|
||||
|
||||
m, err := Meter(meterOptions...).Float64Gauge(name, metricOptions...)
|
||||
// NewFloatGauge creates and returns a Float64Gauge metric instrument with the specified name and options.
|
||||
func NewFloatGauge(name string, opts ...metric.Float64GaugeOption) metric.Float64Gauge {
|
||||
m, err := Meter().Float64Gauge(name, opts...)
|
||||
if err != nil {
|
||||
Ctx(context.TODO()).LogWarn("failed to create Gauge", semconv.ErrorType(err), semconv.ExceptionMessage(err.Error()))
|
||||
otel.Handle(err)
|
||||
return noop.Float64Gauge{}
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// NewIntCounter creates and returns a Int64Counter metric instrument with the specified name and optional settings.
|
||||
func NewIntCounter(name string, opts ...any) metric.Int64Counter {
|
||||
var (
|
||||
meterOptions []metric.MeterOption
|
||||
metricOptions []metric.Int64CounterOption
|
||||
)
|
||||
|
||||
for _, v := range opts {
|
||||
switch t := v.(type) {
|
||||
case metric.MeterOption:
|
||||
meterOptions = append(meterOptions, t)
|
||||
case metric.Int64CounterOption:
|
||||
metricOptions = append(metricOptions, t)
|
||||
default:
|
||||
Ctx(context.TODO()).LogWarn("invalid Counter option", foomosemconv.ReflectType(v))
|
||||
}
|
||||
}
|
||||
|
||||
m, err := Meter(meterOptions...).Int64Counter(name, metricOptions...)
|
||||
// NewIntCounter creates and returns a Int64Counter metric instrument with the specified name and options.
|
||||
func NewIntCounter(name string, opts ...metric.Int64CounterOption) metric.Int64Counter {
|
||||
m, err := Meter().Int64Counter(name, opts...)
|
||||
if err != nil {
|
||||
Ctx(context.TODO()).LogWarn("failed to create Counter", semconv.ErrorType(err), semconv.ExceptionMessage(err.Error()))
|
||||
otel.Handle(err)
|
||||
return noop.Int64Counter{}
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// NewFloatCounter creates and returns a Float64Counter metric instrument with the specified name and optional settings.
|
||||
func NewFloatCounter(name string, opts ...any) metric.Float64Counter {
|
||||
var (
|
||||
meterOptions []metric.MeterOption
|
||||
metricOptions []metric.Float64CounterOption
|
||||
)
|
||||
|
||||
for _, v := range opts {
|
||||
switch t := v.(type) {
|
||||
case metric.MeterOption:
|
||||
meterOptions = append(meterOptions, t)
|
||||
case metric.Float64CounterOption:
|
||||
metricOptions = append(metricOptions, t)
|
||||
default:
|
||||
Ctx(context.TODO()).LogWarn("invalid Counter option", foomosemconv.ReflectType(v))
|
||||
}
|
||||
}
|
||||
|
||||
m, err := Meter(meterOptions...).Float64Counter(name, metricOptions...)
|
||||
// NewFloatCounter creates and returns a Float64Counter metric instrument with the specified name and options.
|
||||
func NewFloatCounter(name string, opts ...metric.Float64CounterOption) metric.Float64Counter {
|
||||
m, err := Meter().Float64Counter(name, opts...)
|
||||
if err != nil {
|
||||
Ctx(context.TODO()).LogWarn("failed to create Counter", semconv.ErrorType(err), semconv.ExceptionMessage(err.Error()))
|
||||
otel.Handle(err)
|
||||
return noop.Float64Counter{}
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// NewIntUpDownCounter creates and returns a Int64UpDownCounter metric instrument with the specified name and optional settings.
|
||||
func NewIntUpDownCounter(name string, opts ...any) metric.Int64UpDownCounter {
|
||||
var (
|
||||
meterOptions []metric.MeterOption
|
||||
metricOptions []metric.Int64UpDownCounterOption
|
||||
)
|
||||
|
||||
for _, v := range opts {
|
||||
switch t := v.(type) {
|
||||
case metric.MeterOption:
|
||||
meterOptions = append(meterOptions, t)
|
||||
case metric.Int64UpDownCounterOption:
|
||||
metricOptions = append(metricOptions, t)
|
||||
default:
|
||||
Ctx(context.TODO()).LogWarn("invalid UpDownCounter option", foomosemconv.ReflectType(v))
|
||||
}
|
||||
}
|
||||
|
||||
m, err := Meter(meterOptions...).Int64UpDownCounter(name, metricOptions...)
|
||||
// NewIntUpDownCounter creates and returns a Int64UpDownCounter metric instrument with the specified name and options.
|
||||
func NewIntUpDownCounter(name string, opts ...metric.Int64UpDownCounterOption) metric.Int64UpDownCounter {
|
||||
m, err := Meter().Int64UpDownCounter(name, opts...)
|
||||
if err != nil {
|
||||
Ctx(context.TODO()).LogWarn("failed to create UpDownCounter", semconv.ErrorType(err), semconv.ExceptionMessage(err.Error()))
|
||||
otel.Handle(err)
|
||||
return noop.Int64UpDownCounter{}
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
// NewFloatUpDownCounter creates and returns a Float64UpDownCounter metric instrument with the specified name and optional settings.
|
||||
func NewFloatUpDownCounter(name string, opts ...any) metric.Float64UpDownCounter {
|
||||
var (
|
||||
meterOptions []metric.MeterOption
|
||||
metricOptions []metric.Float64UpDownCounterOption
|
||||
)
|
||||
|
||||
for _, v := range opts {
|
||||
switch t := v.(type) {
|
||||
case metric.MeterOption:
|
||||
meterOptions = append(meterOptions, t)
|
||||
case metric.Float64UpDownCounterOption:
|
||||
metricOptions = append(metricOptions, t)
|
||||
default:
|
||||
Ctx(context.TODO()).LogWarn("invalid UpDownCounter option", foomosemconv.ReflectType(v))
|
||||
}
|
||||
}
|
||||
|
||||
m, err := Meter(meterOptions...).Float64UpDownCounter(name, metricOptions...)
|
||||
// NewFloatUpDownCounter creates and returns a Float64UpDownCounter metric instrument with the specified name and options.
|
||||
func NewFloatUpDownCounter(name string, opts ...metric.Float64UpDownCounterOption) metric.Float64UpDownCounter {
|
||||
m, err := Meter().Float64UpDownCounter(name, opts...)
|
||||
if err != nil {
|
||||
Ctx(context.TODO()).LogWarn("failed to create UpDownCounter", semconv.ErrorType(err), semconv.ExceptionMessage(err.Error()))
|
||||
otel.Handle(err)
|
||||
return noop.Float64UpDownCounter{}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package telemetry_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/foomo/keel/telemetry"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
)
|
||||
|
||||
// TestNewMetricInstruments verifies the typed constructors build non-nil
|
||||
// instruments and accept the shared/typed options that compile for each kind.
|
||||
func TestNewMetricInstruments(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Shared InstrumentOption (WithDescription/WithUnit) applies to every kind;
|
||||
// WithExplicitBucketBoundaries is histogram-only. Wrong-kind options would
|
||||
// fail to compile — that is the point of the typed signatures.
|
||||
assert.NotNil(t, telemetry.NewIntHistogram("h.int", metric.WithUnit("ms"), metric.WithExplicitBucketBoundaries(1, 2, 5)))
|
||||
assert.NotNil(t, telemetry.NewFloatHistogram("h.float", metric.WithExplicitBucketBoundaries(0.1, 0.5)))
|
||||
assert.NotNil(t, telemetry.NewIntGauge("g.int", metric.WithDescription("d")))
|
||||
assert.NotNil(t, telemetry.NewFloatGauge("g.float"))
|
||||
assert.NotNil(t, telemetry.NewIntCounter("c.int", metric.WithUnit("{req}")))
|
||||
assert.NotNil(t, telemetry.NewFloatCounter("c.float"))
|
||||
assert.NotNil(t, telemetry.NewIntUpDownCounter("ud.int"))
|
||||
assert.NotNil(t, telemetry.NewFloatUpDownCounter("ud.float"))
|
||||
}
|
||||
@@ -74,7 +74,7 @@ func NewProfiler(ctx context.Context) (*pyroscope.Profiler, error) {
|
||||
key = "service_git_ref"
|
||||
case semconv.VCSRepositoryURLFullKey:
|
||||
key = "service_repository"
|
||||
case "vcs_repository_path":
|
||||
case "vcs.repository.path":
|
||||
key = "service_root_path"
|
||||
default:
|
||||
key = strings.ReplaceAll(string(attr.Key), ".", "_")
|
||||
@@ -85,9 +85,8 @@ func NewProfiler(ctx context.Context) (*pyroscope.Profiler, error) {
|
||||
|
||||
p, err := pyroscope.Start(pyroscope.Config{
|
||||
ApplicationName: name,
|
||||
// Logger: internalpyroscope.NewLogger(),
|
||||
ProfileTypes: profileTypes,
|
||||
Tags: tags,
|
||||
ProfileTypes: profileTypes,
|
||||
Tags: tags,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -9,15 +9,15 @@ import (
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.41.0"
|
||||
)
|
||||
|
||||
// ResourceEnvMap maps environment variables to semantic attributes.
|
||||
// envAttributes maps environment variables to semantic attributes.
|
||||
var envAttributes = map[attribute.Key][]string{
|
||||
semconv.VCSRepositoryNameKey: {"REPO_NAME", "REPOSITORY_NAME", "GIT_REPOSITORY_NAME", "GITHUB_REPOSITORY", "GITHUB_REPOSITORY_NAME", "GIT_OTEL_VCS_REPOSITORY_NAME"},
|
||||
semconv.VCSRepositoryURLFullKey: {"REPO_URL", "REPOSITORY_URL", "GIT_REPOSITORY_URL", "OTEL_VCS_REPOSITORY_URL_FULL"},
|
||||
semconv.VCSRefBaseNameKey: {"OTEL_VCS_BASE_NAME"},
|
||||
semconv.VCSRefBaseRevisionKey: {"OTEL_VCS_BASE_REVSION"},
|
||||
semconv.VCSRefBaseRevisionKey: {"OTEL_VCS_BASE_REVISION"},
|
||||
semconv.VCSRefBaseTypeKey: {"OTEL_VCS_BASE_TYPE"},
|
||||
semconv.VCSRefHeadNameKey: {"GIT_BRANCH", "OTEL_VCS_HEAD_NAME"},
|
||||
semconv.VCSRefHeadRevisionKey: {"GIT_COMMIT", "GIT_COMMIT_HASH", "OTEL_VCS_HEAD_REVSION"},
|
||||
semconv.VCSRefHeadRevisionKey: {"GIT_COMMIT", "GIT_COMMIT_HASH", "OTEL_VCS_HEAD_REVISION"},
|
||||
semconv.VCSRefHeadTypeKey: {"GIT_TYPE", "OTEL_VCS_HEAD_TYPE"},
|
||||
"vcs.repository.path": {"REPO_PATH", "REPOSITORY_PATH", "GIT_REPOSITORY_PATH", "OTEL_VCS_ROOT_PATH"},
|
||||
}
|
||||
|
||||
+93
-5
@@ -2,24 +2,112 @@ package telemetry
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
|
||||
goruntime "github.com/foomo/go/runtime"
|
||||
keelsemconv "github.com/foomo/keel/semconv"
|
||||
"github.com/pkg/errors"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.41.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
// Deprecated: use Ctx instead.
|
||||
// Deprecated: use StartSpan instead.
|
||||
func Start(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
|
||||
return Tracer().Start(ctx, spanName, opts...) //nolint:spancheck
|
||||
return startSpan(ctx, 1, opts...)
|
||||
}
|
||||
|
||||
// Deprecated: use Ctx instead.
|
||||
// StartSpan starts a new span with the given name and options.
|
||||
func StartSpan(ctx context.Context, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
|
||||
return startSpan(ctx, 1, opts...)
|
||||
}
|
||||
|
||||
// StartDebugSpan starts a new span with the given name and options and adds the debug attr.
|
||||
func StartDebugSpan(ctx context.Context, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
|
||||
return startSpan(ctx, 1, append(opts, trace.WithAttributes(keelsemconv.DebugEnabled(true)))...)
|
||||
}
|
||||
|
||||
func SpanFromContext(ctx context.Context) trace.Span {
|
||||
return trace.SpanFromContext(ctx)
|
||||
}
|
||||
|
||||
// AddSpanEvent adds an event to the span.
|
||||
func AddSpanEvent(ctx context.Context, name string, opts ...trace.EventOption) {
|
||||
SpanFromContext(ctx).AddEvent(name, opts...)
|
||||
}
|
||||
|
||||
// SetSpanAttributes sets attributes on the span.
|
||||
func SetSpanAttributes(ctx context.Context, attrs ...attribute.KeyValue) {
|
||||
SpanFromContext(ctx).SetAttributes(attrs...)
|
||||
}
|
||||
|
||||
// SetSpanName sets the name of the span.
|
||||
func SetSpanName(ctx context.Context, name string) {
|
||||
SpanFromContext(ctx).SetName(name)
|
||||
}
|
||||
|
||||
// IsSpanRecording returns true if the span is recording.
|
||||
func IsSpanRecording(ctx context.Context) bool {
|
||||
return SpanFromContext(ctx).IsRecording()
|
||||
}
|
||||
|
||||
// SetSpanDebug sets the span debug attribute.
|
||||
func SetSpanDebug(ctx context.Context) {
|
||||
SpanFromContext(ctx).SetAttributes(keelsemconv.DebugEnabled(true))
|
||||
}
|
||||
|
||||
// SetSpanStatusOK sets the status of the span to ok.
|
||||
func SetSpanStatusOK(ctx context.Context) {
|
||||
SpanFromContext(ctx).SetStatus(codes.Ok, "")
|
||||
}
|
||||
|
||||
// SetSpanStatusError sets the status of the span to error.
|
||||
func SetSpanStatusError(ctx context.Context, description string) {
|
||||
SpanFromContext(ctx).SetStatus(codes.Error, description)
|
||||
}
|
||||
|
||||
// Deprecated: use EndSpan instead.
|
||||
func End(sp trace.Span, err error) {
|
||||
if err != nil {
|
||||
sp.RecordError(err)
|
||||
sp.SetStatus(codes.Error, err.Error())
|
||||
sp.RecordError(err, trace.WithAttributes(CodeStacktrace(3, 0)))
|
||||
sp.SetStatus(codes.Error, errors.Cause(err).Error())
|
||||
} else {
|
||||
sp.SetStatus(codes.Ok, "")
|
||||
}
|
||||
|
||||
sp.End()
|
||||
}
|
||||
|
||||
// EndSpan ends the span.
|
||||
func EndSpan(ctx context.Context, err error, opts ...trace.SpanEndOption) {
|
||||
sp := SpanFromContext(ctx)
|
||||
if err != nil {
|
||||
sp.RecordError(err, trace.WithAttributes(CodeStacktrace(3, 0)))
|
||||
sp.SetStatus(codes.Error, errors.Cause(err).Error())
|
||||
}
|
||||
|
||||
sp.End(opts...)
|
||||
}
|
||||
|
||||
// DeferEndSpan is a helper, so you can do `defer ctx.DeferEndSpan(&err)` instead of `defer func(){ ctx.EndSpan(err) }()`
|
||||
func DeferEndSpan(ctx context.Context, err *error, opts ...trace.SpanEndOption) {
|
||||
EndSpan(ctx, *err)
|
||||
}
|
||||
|
||||
func startSpan(ctx context.Context, skip int, opts ...trace.SpanStartOption) (Context, trace.Span) {
|
||||
name := "runtime.go"
|
||||
|
||||
if fr := goruntime.CallFrame(skip + 1); !fr.Zero() {
|
||||
name = path.Base(fr.Pkg)
|
||||
opts = append(opts, trace.WithAttributes(
|
||||
semconv.CodeFunctionName(fr.Name()),
|
||||
semconv.CodeLineNumber(fr.Line),
|
||||
semconv.CodeFilePath(fr.File),
|
||||
))
|
||||
}
|
||||
|
||||
ctx, span := Tracer().Start(ctx, name, opts...) //nolint:spancheck
|
||||
|
||||
return Ctx(ctx), span //nolint:spancheck
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ func TracerProvider() trace.TracerProvider {
|
||||
return otel.GetTracerProvider()
|
||||
}
|
||||
|
||||
// NewNoopTraceProvider creates and returns a no-op tracer provider, setting it as the global otel tracer provider.
|
||||
// NewNoopTraceProvider creates and returns a no-op tracer provider.
|
||||
func NewNoopTraceProvider() trace.TracerProvider {
|
||||
return noop.NewTracerProvider()
|
||||
}
|
||||
|
||||
+3
-1
@@ -5,6 +5,8 @@ import (
|
||||
)
|
||||
|
||||
// Tracer returns a trace.Tracer instance configured with optional TracerOptions.
|
||||
// The instrumentation scope version defaults to the keel module version; pass a
|
||||
// trace.WithInstrumentationVersion option to override it.
|
||||
func Tracer(opts ...trace.TracerOption) trace.Tracer {
|
||||
return TracerProvider().Tracer(Name, opts...)
|
||||
return TracerProvider().Tracer(Name, append([]trace.TracerOption{trace.WithInstrumentationVersion(Version())}, opts...)...)
|
||||
}
|
||||
|
||||
+188
-21
@@ -1,11 +1,12 @@
|
||||
package httputils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
httplog "github.com/foomo/keel/net/http/log"
|
||||
"github.com/foomo/keel/telemetry"
|
||||
"github.com/pkg/errors"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.41.0"
|
||||
"go.uber.org/zap"
|
||||
|
||||
@@ -13,53 +14,219 @@ import (
|
||||
)
|
||||
|
||||
// InternalServerError http response
|
||||
func InternalServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, err error) {
|
||||
ServerError(l, w, r, http.StatusInternalServerError, err)
|
||||
func InternalServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusInternalServerError, errs...)
|
||||
}
|
||||
|
||||
// InternalServiceUnavailable http response
|
||||
func InternalServiceUnavailable(l *zap.Logger, w http.ResponseWriter, r *http.Request, err error) {
|
||||
ServerError(l, w, r, http.StatusServiceUnavailable, err)
|
||||
func InternalServiceUnavailable(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusServiceUnavailable, errs...)
|
||||
}
|
||||
|
||||
// InternalServiceTooEarly http response
|
||||
func InternalServiceTooEarly(l *zap.Logger, w http.ResponseWriter, r *http.Request, err error) {
|
||||
ServerError(l, w, r, http.StatusTooEarly, err)
|
||||
func InternalServiceTooEarly(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusTooEarly, errs...)
|
||||
}
|
||||
|
||||
// UnauthorizedServerError http response
|
||||
func UnauthorizedServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, err error) {
|
||||
ServerError(l, w, r, http.StatusUnauthorized, err)
|
||||
func UnauthorizedServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusUnauthorized, errs...)
|
||||
}
|
||||
|
||||
// BadRequestServerError http response
|
||||
func BadRequestServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, err error) {
|
||||
ServerError(l, w, r, http.StatusBadRequest, err)
|
||||
func BadRequestServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusBadRequest, errs...)
|
||||
}
|
||||
|
||||
// MethodNotAllowedServerError http response
|
||||
func MethodNotAllowedServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, err error) {
|
||||
ServerError(l, w, r, http.StatusMethodNotAllowed, err)
|
||||
func MethodNotAllowedServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusMethodNotAllowed, errs...)
|
||||
}
|
||||
|
||||
// RequestEntityTooLargeServerError http response
|
||||
func RequestEntityTooLargeServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, err error) {
|
||||
ServerError(l, w, r, http.StatusRequestEntityTooLarge, err)
|
||||
func RequestEntityTooLargeServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusRequestEntityTooLarge, errs...)
|
||||
}
|
||||
|
||||
// NotFoundServerError http response
|
||||
func NotFoundServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, err error) {
|
||||
ServerError(l, w, r, http.StatusNotFound, err)
|
||||
func NotFoundServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusNotFound, errs...)
|
||||
}
|
||||
|
||||
// PaymentRequiredServerError http response
|
||||
func PaymentRequiredServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusPaymentRequired, errs...)
|
||||
}
|
||||
|
||||
// ForbiddenServerError http response
|
||||
func ForbiddenServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusForbidden, errs...)
|
||||
}
|
||||
|
||||
// NotAcceptableServerError http response
|
||||
func NotAcceptableServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusNotAcceptable, errs...)
|
||||
}
|
||||
|
||||
// ProxyAuthRequiredServerError http response
|
||||
func ProxyAuthRequiredServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusProxyAuthRequired, errs...)
|
||||
}
|
||||
|
||||
// RequestTimeoutServerError http response
|
||||
func RequestTimeoutServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusRequestTimeout, errs...)
|
||||
}
|
||||
|
||||
// ConflictServerError http response
|
||||
func ConflictServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusConflict, errs...)
|
||||
}
|
||||
|
||||
// GoneServerError http response
|
||||
func GoneServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusGone, errs...)
|
||||
}
|
||||
|
||||
// LengthRequiredServerError http response
|
||||
func LengthRequiredServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusLengthRequired, errs...)
|
||||
}
|
||||
|
||||
// PreconditionFailedServerError http response
|
||||
func PreconditionFailedServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusPreconditionFailed, errs...)
|
||||
}
|
||||
|
||||
// RequestURITooLongServerError http response
|
||||
func RequestURITooLongServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusRequestURITooLong, errs...)
|
||||
}
|
||||
|
||||
// UnsupportedMediaTypeServerError http response
|
||||
func UnsupportedMediaTypeServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusUnsupportedMediaType, errs...)
|
||||
}
|
||||
|
||||
// RequestedRangeNotSatisfiableServerError http response
|
||||
func RequestedRangeNotSatisfiableServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusRequestedRangeNotSatisfiable, errs...)
|
||||
}
|
||||
|
||||
// ExpectationFailedServerError http response
|
||||
func ExpectationFailedServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusExpectationFailed, errs...)
|
||||
}
|
||||
|
||||
// TeapotServerError http response
|
||||
func TeapotServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusTeapot, errs...)
|
||||
}
|
||||
|
||||
// MisdirectedRequestServerError http response
|
||||
func MisdirectedRequestServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusMisdirectedRequest, errs...)
|
||||
}
|
||||
|
||||
// UnprocessableEntityServerError http response
|
||||
func UnprocessableEntityServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusUnprocessableEntity, errs...)
|
||||
}
|
||||
|
||||
// LockedServerError http response
|
||||
func LockedServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusLocked, errs...)
|
||||
}
|
||||
|
||||
// FailedDependencyServerError http response
|
||||
func FailedDependencyServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusFailedDependency, errs...)
|
||||
}
|
||||
|
||||
// UpgradeRequiredServerError http response
|
||||
func UpgradeRequiredServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusUpgradeRequired, errs...)
|
||||
}
|
||||
|
||||
// PreconditionRequiredServerError http response
|
||||
func PreconditionRequiredServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusPreconditionRequired, errs...)
|
||||
}
|
||||
|
||||
// TooManyRequestsServerError http response
|
||||
func TooManyRequestsServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusTooManyRequests, errs...)
|
||||
}
|
||||
|
||||
// RequestHeaderFieldsTooLargeServerError http response
|
||||
func RequestHeaderFieldsTooLargeServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusRequestHeaderFieldsTooLarge, errs...)
|
||||
}
|
||||
|
||||
// UnavailableForLegalReasonsServerError http response
|
||||
func UnavailableForLegalReasonsServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusUnavailableForLegalReasons, errs...)
|
||||
}
|
||||
|
||||
// NotImplementedServerError http response
|
||||
func NotImplementedServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusNotImplemented, errs...)
|
||||
}
|
||||
|
||||
// BadGatewayServerError http response
|
||||
func BadGatewayServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusBadGateway, errs...)
|
||||
}
|
||||
|
||||
// GatewayTimeoutServerError http response
|
||||
func GatewayTimeoutServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusGatewayTimeout, errs...)
|
||||
}
|
||||
|
||||
// HTTPVersionNotSupportedServerError http response
|
||||
func HTTPVersionNotSupportedServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusHTTPVersionNotSupported, errs...)
|
||||
}
|
||||
|
||||
// VariantAlsoNegotiatesServerError http response
|
||||
func VariantAlsoNegotiatesServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusVariantAlsoNegotiates, errs...)
|
||||
}
|
||||
|
||||
// InsufficientStorageServerError http response
|
||||
func InsufficientStorageServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusInsufficientStorage, errs...)
|
||||
}
|
||||
|
||||
// LoopDetectedServerError http response
|
||||
func LoopDetectedServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusLoopDetected, errs...)
|
||||
}
|
||||
|
||||
// NotExtendedServerError http response
|
||||
func NotExtendedServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusNotExtended, errs...)
|
||||
}
|
||||
|
||||
// NetworkAuthenticationRequiredServerError http response
|
||||
func NetworkAuthenticationRequiredServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, errs ...error) {
|
||||
ServerError(l, w, r, http.StatusNetworkAuthenticationRequired, errs...)
|
||||
}
|
||||
|
||||
// ServerError http response
|
||||
func ServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, code int, err error) {
|
||||
if err != nil {
|
||||
func ServerError(l *zap.Logger, w http.ResponseWriter, r *http.Request, code int, errs ...error) {
|
||||
if err := errors.Join(errs...); err != nil {
|
||||
errType := semconv.ErrorType(err)
|
||||
telemetry.Ctx(r.Context()).RecordError(err)
|
||||
|
||||
if labeler, ok := otelhttp.LabelerFromContext(r.Context()); ok {
|
||||
labeler.Add(errType)
|
||||
}
|
||||
|
||||
// add log entry
|
||||
if labeler, ok := httplog.LabelerFromRequest(r); ok {
|
||||
labeler.Add(log.FErrorType(err), log.FError(errors.Wrap(err, "http server error")))
|
||||
} else {
|
||||
labeler.Add(log.Attribute(errType), log.FError(err))
|
||||
} else if l != nil {
|
||||
l = log.WithError(l, err)
|
||||
l = log.WithHTTPRequest(l, r)
|
||||
l.Error("http server error", log.Attribute(semconv.HTTPResponseStatusCode(code)))
|
||||
|
||||
Reference in New Issue
Block a user