From feb8e32069b76db36456362ddd0d1b3f918ac797 Mon Sep 17 00:00:00 2001 From: ErickSkrauch Date: Wed, 14 Feb 2024 00:56:48 +0100 Subject: [PATCH 1/3] Add otel setup --- go.mod | 31 +++++++- go.sum | 111 ++++++++++++++++++++++++--- internal/cmd/root.go | 20 ----- internal/cmd/serve.go | 43 +++++++++++ internal/di/context.go | 21 +++++ internal/di/db.go | 6 +- internal/di/di.go | 7 +- internal/di/handlers.go | 2 + internal/di/server.go | 46 ++++------- internal/http/http.go | 11 +-- internal/otel/setup.go | 164 ++++++++++++++++++++++++++++++++++++++++ 11 files changed, 380 insertions(+), 82 deletions(-) create mode 100644 internal/di/context.go create mode 100644 internal/otel/setup.go diff --git a/go.mod b/go.mod index effa7d1..2106628 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,9 @@ go 1.21 // Main dependencies require ( + github.com/SentimensRG/ctx v0.0.0-20180729130232-0bfd988c655d + github.com/agoda-com/opentelemetry-go/otelslog v0.1.1 + github.com/agoda-com/opentelemetry-logs-go v0.4.3 github.com/brunomvsouza/singleflight v0.4.0 github.com/defval/di v1.12.0 github.com/etherlabsio/healthcheck/v2 v2.0.0 @@ -14,10 +17,18 @@ require ( github.com/jellydator/ttlcache/v3 v3.1.1 github.com/mediocregopher/radix/v4 v4.1.4 github.com/mono83/slf v0.0.0-20170919161409-79153e9636db - github.com/SentimensRG/ctx v0.0.0-20180729130232-0bfd988c655d github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.18.1 github.com/valyala/fastjson v1.6.4 + go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.48.0 + go.opentelemetry.io/contrib/instrumentation/runtime v0.48.0 + go.opentelemetry.io/otel v1.23.1 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.23.1 + go.opentelemetry.io/otel/metric v1.23.1 + go.opentelemetry.io/otel/sdk v1.23.1 + go.opentelemetry.io/otel/sdk/metric v1.23.1 + go.opentelemetry.io/otel/trace v1.23.1 ) // Dev dependencies @@ -28,12 +39,18 @@ require ( // Indirect dependencies require ( + github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect + github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -51,13 +68,19 @@ require ( github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/tilinna/clock v1.0.2 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1 // indirect + go.opentelemetry.io/proto/otlp v1.1.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.16.0 // indirect + golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect - golang.org/x/net v0.19.0 // indirect + golang.org/x/net v0.21.0 // indirect golang.org/x/sync v0.5.0 // indirect - golang.org/x/sys v0.15.0 // indirect + golang.org/x/sys v0.17.0 // indirect golang.org/x/text v0.14.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014 // indirect + google.golang.org/grpc v1.61.0 // indirect + google.golang.org/protobuf v1.32.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 81bc695..f53e131 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,13 @@ +github.com/SentimensRG/ctx v0.0.0-20180729130232-0bfd988c655d h1:CbB/Ef3TyBvSSJx2HDSUiw49ONTpaX6BGiI0jJEX6b8= +github.com/SentimensRG/ctx v0.0.0-20180729130232-0bfd988c655d/go.mod h1:cfn0Ycx1ASzCkl8+04zI4hrclf9YQ1QfncxzFiNtQLo= +github.com/agoda-com/opentelemetry-go/otelslog v0.1.1 h1:6nV8PZCzySHuh9kP/HZ2OJqGucwQiM+yZRugKDvtzj4= +github.com/agoda-com/opentelemetry-go/otelslog v0.1.1/go.mod h1:CSc0veIcY/HsIfH7l5PGtIpRvBttk09QUQlweVkD2PI= +github.com/agoda-com/opentelemetry-logs-go v0.4.3 h1:dYAx/q9di+/Pv6HuGq59DFIOjqKT0LTy3PYTIz8ccq8= +github.com/agoda-com/opentelemetry-logs-go v0.4.3/go.mod h1:gPQ0fHqroxNP2DlQFZt29/pfqGiP2m6Q5CCxEgLo6yQ= github.com/brunomvsouza/singleflight v0.4.0 h1:9dNcTeYoXSus3xbZEM0EEZ11EcCRjUZOvVW8rnDMG5Y= github.com/brunomvsouza/singleflight v0.4.0/go.mod h1:8RYo9j5WQRupmsnUz5DlUWZxDLNi+t9Zhj3EZFmns7I= +github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= +github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV47EEXL8mWmRdEfGscSJ+7EgePNgt0s= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= @@ -11,6 +19,8 @@ github.com/defval/di v1.12.0 h1:xXm7BMX2+Nr0Yyu55DeJl/rmfCA7CQX89f4AGE0zA6U= github.com/defval/di v1.12.0/go.mod h1:PhVbOxQOvU7oawTOJXXTvqOJp1Dvsjs5PuzMw9gGl0I= github.com/etherlabsio/healthcheck/v2 v2.0.0 h1:oKq8cbpwM/yNGPXf2Sff6MIjVUjx/pGYFydWzeK2MpA= github.com/etherlabsio/healthcheck/v2 v2.0.0/go.mod h1:huNVOjKzu6FI1eaO1CGD3ZjhrmPWf5Obu/pzpI6/wog= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= @@ -19,6 +29,14 @@ github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/getsentry/raven-go v0.2.1-0.20190419175539-919484f041ea h1:t6e33/eet/VyiHHHKs0cBytUISUWQ/hmQwOlqtFoGEo= github.com/getsentry/raven-go v0.2.1-0.20190419175539-919484f041ea/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +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-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -29,10 +47,18 @@ github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0QDGLKzqOmktBjT+Is= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/h2non/gock v1.2.0 h1:K6ol8rfrRkUOefooBC8elXoaNGYkpp7y2qcxGG6BzUE= github.com/h2non/gock v1.2.0/go.mod h1:tNhoxHYW2W42cYkYb1WqzdbYIieALC99kpYr7rH/BQk= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= @@ -49,6 +75,9 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed h1:036IscGBfJsFIgJQzlui7nK1Ncm0tp2ktmPj8xO4N/0= +github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mediocregopher/radix/v4 v4.1.4 h1:Uze6DEbEAvL+VHXUEu/EDBTkUk5CLct5h3nVSGpc6Ts= @@ -64,13 +93,21 @@ github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdU github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= -github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= +github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= +github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= @@ -97,27 +134,79 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tilinna/clock v1.0.2 h1:6BO2tyAC9JbPExKH/z9zl44FLu1lImh3nDNKA0kgrkI= github.com/tilinna/clock v1.0.2/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4= +github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= +github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= +github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.48.0 h1:7rkdNoXgScpSUIqBch/VOB24fk9g0wl3Tr5WPtshi9o= +go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.48.0/go.mod h1:U3t9uswWhDzieXHMNWP6zk87J4HNondiibKMdNLpnMk= +go.opentelemetry.io/contrib/instrumentation/host v0.48.0 h1:eVDLR/hletJcctz4rSWwb3QVzRnEQKuTVi6qAm7fsWs= +go.opentelemetry.io/contrib/instrumentation/host v0.48.0/go.mod h1:dWSGvPpaGKwBh/dpLJs6pczyOc82hBnxa1YTQZCic0I= +go.opentelemetry.io/contrib/instrumentation/runtime v0.48.0 h1:dJlCKeq+zmO5Og4kgxqPvvJrzuD/mygs1g/NYM9dAsU= +go.opentelemetry.io/contrib/instrumentation/runtime v0.48.0/go.mod h1:p+hpBCpLHpuUrR0lHgnHbUnbCBll1IhrcMIlycC+xYs= +go.opentelemetry.io/otel v1.23.1 h1:Za4UzOqJYS+MUczKI320AtqZHZb7EqxO00jAHE0jmQY= +go.opentelemetry.io/otel v1.23.1/go.mod h1:Td0134eafDLcTS4y+zQ26GE8u3dEuRBiBCTUIRHaikA= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1 h1:q/Nj5/2TZRIt6PderQ9oU0M00fzoe8UZuINGw6ETGTw= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1/go.mod h1:DTE9yAu6r08jU3xa68GiSeI7oRcSEQ2RpKbbQGO+dWM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1 h1:o8iWeVFa1BcLtVEV0LzrCxV2/55tB3xLxADr6Kyoey4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1/go.mod h1:SEVfdK4IoBnbT2FXNM/k8yC08MrfbhWk3U4ljM8B3HE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.23.1 h1:cfuy3bXmLJS7M1RZmAL6SuhGtKUp2KEsrm00OlAXkq4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.23.1/go.mod h1:22jr92C6KwlwItJmQzfixzQM3oyyuYLCfHiMY+rpsPU= +go.opentelemetry.io/otel/metric v1.23.1 h1:PQJmqJ9u2QaJLBOELl1cxIdPcpbwzbkjfEyelTl2rlo= +go.opentelemetry.io/otel/metric v1.23.1/go.mod h1:mpG2QPlAfnK8yNhNJAxDZruU9Y1/HubbC+KyH8FaCWI= +go.opentelemetry.io/otel/sdk v1.23.1 h1:O7JmZw0h76if63LQdsBMKQDWNb5oEcOThG9IrxscV+E= +go.opentelemetry.io/otel/sdk v1.23.1/go.mod h1:LzdEVR5am1uKOOwfBWFef2DCi1nu3SA8XQxx2IerWFk= +go.opentelemetry.io/otel/sdk/metric v1.23.1 h1:T9/8WsYg+ZqIpMWwdISVVrlGb/N0Jr1OHjR/alpKwzg= +go.opentelemetry.io/otel/sdk/metric v1.23.1/go.mod h1:8WX6WnNtHCgUruJ4TJ+UssQjMtpxkpX0zveQC8JG/E0= +go.opentelemetry.io/otel/trace v1.23.1 h1:4LrmmEd8AU2rFvU1zegmvqW7+kWarxtNOPyeL6HmYY8= +go.opentelemetry.io/otel/trace v1.23.1/go.mod h1:4IpnpJFwr1mo/6HL8XIPJaE9y0+u1KcVmuW7dwFSVrI= +go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= +go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= -golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8= golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI= -golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= -golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe h1:USL2DhxfgRchafRvt/wYyyQNzwgL7ZiURcozOE/Pkvo= +google.golang.org/genproto v0.0.0-20240125205218-1f4bbc51befe/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 h1:x9PwdEgd11LgK+orcck69WVRo7DezSO4VUMPI4xpc8A= +google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014/go.mod h1:rbHMSEDyoYX62nRVLOCc4Qt1HbsdytAYoVwgjiOhF3I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014 h1:FSL3lRCkhaPFxqi0s9o+V4UI2WTzAVOvkgbd4kVV4Wg= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014/go.mod h1:SaPjaZGWb0lPqs6Ittu0spdfrOArqji4ZdeP5IC/9N4= +google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= +google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/cmd/root.go b/internal/cmd/root.go index 7d0c801..f53485b 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -8,7 +8,6 @@ import ( "github.com/spf13/viper" "ely.by/chrly/internal/di" - "ely.by/chrly/internal/http" "ely.by/chrly/internal/version" ) @@ -27,25 +26,6 @@ func shouldGetContainer() *Container { return container } -func startServer(modules ...string) error { - container := shouldGetContainer() - - var config *viper.Viper - err := container.Resolve(&config) - if err != nil { - return err - } - - config.Set("modules", modules) - - err = container.Invoke(http.StartServer) - if err != nil { - return err - } - - return nil -} - func init() { cobra.OnInitialize(initConfig) } diff --git a/internal/cmd/serve.go b/internal/cmd/serve.go index 9a9246f..6a7fac3 100644 --- a/internal/cmd/serve.go +++ b/internal/cmd/serve.go @@ -1,7 +1,14 @@ package cmd import ( + "context" + "log/slog" + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "ely.by/chrly/internal/http" + "ely.by/chrly/internal/otel" ) var serveCmd = &cobra.Command{ @@ -15,3 +22,39 @@ var serveCmd = &cobra.Command{ func init() { RootCmd.AddCommand(serveCmd) } + +func startServer(modules ...string) error { + container := shouldGetContainer() + + var globalCtx context.Context + err := container.Resolve(&globalCtx) + if err != nil { + return err + } + + shutdownOtel, err := otel.SetupOTelSDK(globalCtx) + defer func() { + err := shutdownOtel(context.Background()) + if err != nil { + slog.Error("Unable to shutdown OpenTelemetry", slog.Any("error", err)) + } + }() + if err != nil { + return err + } + + var config *viper.Viper + err = container.Resolve(&config) + if err != nil { + return err + } + + config.Set("modules", modules) + + err = container.Invoke(http.StartServer) + if err != nil { + return err + } + + return nil +} diff --git a/internal/di/context.go b/internal/di/context.go new file mode 100644 index 0000000..17516ba --- /dev/null +++ b/internal/di/context.go @@ -0,0 +1,21 @@ +package di + +import ( + "context" + "os" + "os/signal" + "syscall" + + "github.com/defval/di" +) + +var contextDiOptions = di.Options( + di.Provide(newBaseContext), +) + +func newBaseContext() context.Context { + ctx := context.Background() + ctx, _ = signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM, os.Kill) + + return ctx +} diff --git a/internal/di/db.go b/internal/di/db.go index 6f098bf..6d8f559 100644 --- a/internal/di/db.go +++ b/internal/di/db.go @@ -16,7 +16,7 @@ import ( // Since there are no options for selecting target backends, // all constants in this case point to static specific implementations. -var dbDeOptions = di.Options( +var dbDiOptions = di.Options( di.Provide(newRedis, di.As(new(profiles.ProfilesRepository)), di.As(new(profiles.ProfilesFinder)), @@ -24,13 +24,13 @@ var dbDeOptions = di.Options( ), ) -func newRedis(container *di.Container, config *viper.Viper) (*redis.Redis, error) { +func newRedis(container *di.Container, ctx context.Context, config *viper.Viper) (*redis.Redis, error) { config.SetDefault("storage.redis.host", "localhost") config.SetDefault("storage.redis.port", 6379) config.SetDefault("storage.redis.poolSize", 10) conn, err := redis.New( - context.Background(), + ctx, db.NewZlibEncoder(&db.JsonSerializer{}), fmt.Sprintf("%s:%d", config.GetString("storage.redis.host"), config.GetInt("storage.redis.port")), config.GetInt("storage.redis.poolSize"), diff --git a/internal/di/di.go b/internal/di/di.go index 4036b66..0e1b2cb 100644 --- a/internal/di/di.go +++ b/internal/di/di.go @@ -5,12 +5,13 @@ import "github.com/defval/di" func New() (*di.Container, error) { return di.New( configDiOptions, + contextDiOptions, + dbDiOptions, + handlersDiOptions, loggerDiOptions, - dbDeOptions, mojangDiOptions, - handlersDiOptions, profilesDiOptions, - serverDiOptions, securityDiOptions, + serverDiOptions, ) } diff --git a/internal/di/handlers.go b/internal/di/handlers.go index 91f42ac..5a643e4 100644 --- a/internal/di/handlers.go +++ b/internal/di/handlers.go @@ -9,6 +9,7 @@ import ( "github.com/etherlabsio/healthcheck/v2" "github.com/gorilla/mux" "github.com/spf13/viper" + "go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux" . "ely.by/chrly/internal/http" ) @@ -39,6 +40,7 @@ func newHandlerFactory( } router.StrictSlash(true) + router.Use(otelmux.Middleware("chrly")) router.NotFoundHandler = http.HandlerFunc(NotFoundHandler) if slices.Contains(enabledModules, "api") { diff --git a/internal/di/server.go b/internal/di/server.go index 0f2cba4..fd8a61f 100644 --- a/internal/di/server.go +++ b/internal/di/server.go @@ -8,7 +8,6 @@ import ( "time" "github.com/defval/di" - "github.com/getsentry/raven-go" "github.com/spf13/viper" . "ely.by/chrly/internal/http" @@ -29,41 +28,22 @@ func newAuthenticator(config *viper.Viper) (*security.Jwt, error) { return security.NewJwt([]byte(key)), nil } -type serverParams struct { - di.Inject +func newServer(Config *viper.Viper, Handler http.Handler) *http.Server { + Config.SetDefault("server.host", "") + Config.SetDefault("server.port", 80) - Config *viper.Viper `di:""` - Handler http.Handler `di:""` - Sentry *raven.Client `di:"" optional:"true"` -} - -func newServer(params serverParams) *http.Server { - params.Config.SetDefault("server.host", "") - params.Config.SetDefault("server.port", 80) + var handler http.Handler = http.HandlerFunc(func(request http.ResponseWriter, response *http.Request) { + defer func() { + if recovered := recover(); recovered != nil { + debug.PrintStack() + request.WriteHeader(http.StatusInternalServerError) + } + }() - var handler http.Handler - if params.Sentry != nil { - // raven.Recoverer uses DefaultClient and nothing can be done about it - // To avoid code duplication, if the Sentry service is successfully initiated, - // it will also replace DefaultClient, so raven.Recoverer will work with the instance - // created in the application constructor - handler = raven.Recoverer(params.Handler) - } else { - // Raven's Recoverer is prints the stacktrace and sets the corresponding status itself. - // But there is no magic and if you don't define a panic handler, Mux will just reset the connection - handler = http.HandlerFunc(func(request http.ResponseWriter, response *http.Request) { - defer func() { - if recovered := recover(); recovered != nil { - debug.PrintStack() // TODO: colorize output - request.WriteHeader(http.StatusInternalServerError) - } - }() - - params.Handler.ServeHTTP(request, response) - }) - } + Handler.ServeHTTP(request, response) + }) - address := fmt.Sprintf("%s:%d", params.Config.GetString("server.host"), params.Config.GetInt("server.port")) + address := fmt.Sprintf("%s:%d", Config.GetString("server.host"), Config.GetInt("server.port")) server := &http.Server{ Addr: address, ReadTimeout: 5 * time.Second, diff --git a/internal/http/http.go b/internal/http/http.go index d6f9565..3d9477f 100644 --- a/internal/http/http.go +++ b/internal/http/http.go @@ -3,10 +3,8 @@ package http import ( "context" "encoding/json" + "log/slog" "net/http" - "os" - "os/signal" - "syscall" "time" "github.com/gorilla/mux" @@ -16,11 +14,8 @@ import ( "ely.by/chrly/internal/version" ) -func StartServer(server *http.Server, logger slf.Logger) { - logger.Debug("Chrly :v (:c)", wd.StringParam("v", version.Version()), wd.StringParam("c", version.Commit())) - - ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM, os.Kill) - defer cancel() +func StartServer(ctx context.Context, server *http.Server, logger slf.Logger) { + slog.Debug("Chrly :v (:c)", slog.String("v", version.Version()), slog.String("c", version.Commit())) srvErr := make(chan error, 1) go func() { diff --git a/internal/otel/setup.go b/internal/otel/setup.go new file mode 100644 index 0000000..4c6b115 --- /dev/null +++ b/internal/otel/setup.go @@ -0,0 +1,164 @@ +package otel + +import ( + "context" + "errors" + "log/slog" + "time" + + "github.com/agoda-com/opentelemetry-go/otelslog" + logsOtel "github.com/agoda-com/opentelemetry-logs-go" + "github.com/agoda-com/opentelemetry-logs-go/exporters/otlp/otlplogs" + "github.com/agoda-com/opentelemetry-logs-go/sdk/logs" + logsSdk "github.com/agoda-com/opentelemetry-logs-go/sdk/logs" + runtimeMetrics "go.opentelemetry.io/contrib/instrumentation/runtime" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" + "go.opentelemetry.io/otel/propagation" + "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/sdk/resource" + "go.opentelemetry.io/otel/sdk/trace" + "go.opentelemetry.io/otel/semconv/v1.4.0" + + "ely.by/chrly/internal/version" +) + +func SetupOTelSDK(ctx context.Context) (shutdown func(context.Context) error, err error) { + var shutdownFuncs []func(context.Context) error + + // shutdown calls cleanup functions registered via shutdownFuncs. + // The errors from the calls are joined. + // Each registered cleanup will be invoked once + shutdown = func(ctx context.Context) error { + var err error + for _, fn := range shutdownFuncs { + err = errors.Join(err, fn(ctx)) + } + + shutdownFuncs = nil + + return err + } + + // handleErr calls shutdown for cleanup and makes sure that all errors are returned + handleErr := func(inErr error) { + err = errors.Join(inErr, shutdown(ctx)) + } + + // Set up propagator + prop := newPropagator() + otel.SetTextMapPropagator(prop) + + // Set up resource + res, err := newResource(ctx) + if err != nil { + handleErr(err) + return + } + + // Set up logs provider + logsProvider, err := newLoggerProvider(ctx, res) + if err != nil { + handleErr(err) + return + } + + shutdownFuncs = append(shutdownFuncs, logsProvider.Shutdown) + logsOtel.SetLoggerProvider(logsProvider) + + otelSlog := slog.New(otelslog.NewOtelHandler(logsProvider, &otelslog.HandlerOptions{Level: slog.LevelDebug})) + slog.SetDefault(otelSlog) + + // Set up trace provider + tracerProvider, err := newTraceProvider(ctx, res) + if err != nil { + handleErr(err) + return + } + + shutdownFuncs = append(shutdownFuncs, tracerProvider.Shutdown) + otel.SetTracerProvider(tracerProvider) + + // Set up meter provider + meterProvider, err := newMeterProvider(ctx, res) + if err != nil { + handleErr(err) + return + } + + shutdownFuncs = append(shutdownFuncs, meterProvider.Shutdown) + otel.SetMeterProvider(meterProvider) + + err = runtimeMetrics.Start(runtimeMetrics.WithMinimumReadMemStatsInterval(time.Second)) + if err != nil { + handleErr(err) + return + } + + return +} + +func newPropagator() propagation.TextMapPropagator { + return propagation.NewCompositeTextMapPropagator( + propagation.TraceContext{}, + propagation.Baggage{}, + ) +} + +func newResource(ctx context.Context) (*resource.Resource, error) { + return resource.New( + ctx, + resource.WithFromEnv(), + resource.WithTelemetrySDK(), + resource.WithOS(), + resource.WithContainer(), + resource.WithHost(), + resource.WithAttributes( + semconv.ServiceNameKey.String("chrly"), + semconv.ServiceVersionKey.String(version.Version()), + ), + ) +} + +func newLoggerProvider(ctx context.Context, res *resource.Resource) (*logs.LoggerProvider, error) { + exporter, err := otlplogs.NewExporter(ctx) + if err != nil { + return nil, err + } + + loggerProvider := logsSdk.NewLoggerProvider( + logsSdk.WithBatcher(exporter), + logsSdk.WithResource(res), + ) + + return loggerProvider, nil +} + +func newTraceProvider(ctx context.Context, res *resource.Resource) (*trace.TracerProvider, error) { + traceExporter, err := otlptracehttp.New(ctx) + if err != nil { + return nil, err + } + + traceProvider := trace.NewTracerProvider( + trace.WithResource(res), + trace.WithBatcher(traceExporter), + ) + + return traceProvider, nil +} + +func newMeterProvider(ctx context.Context, res *resource.Resource) (*metric.MeterProvider, error) { + metricExporter, err := otlpmetrichttp.New(ctx) + if err != nil { + return nil, err + } + + meterProvider := metric.NewMeterProvider( + metric.WithResource(res), + metric.WithReader(metric.NewPeriodicReader(metricExporter)), + ) + + return meterProvider, nil +} From f037fb11e107d48355c22f2b0a0dd7a1bcf4f080 Mon Sep 17 00:00:00 2001 From: ErickSkrauch Date: Mon, 19 Feb 2024 13:54:12 +0100 Subject: [PATCH 2/3] progress [skip ci] --- go.mod | 4 +- go.sum | 37 +-------- internal/di/di.go | 1 + internal/di/httpClient.go | 18 +++++ internal/di/mojang.go | 38 ++++----- internal/di/profiles.go | 10 +-- internal/mojang/batch_uuids_provider.go | 73 ++++++++++++++--- internal/mojang/batch_uuids_provider_test.go | 2 +- internal/mojang/client.go | 1 + internal/mojang/provider.go | 83 ++++++++++++++++++- internal/mojang/provider_test.go | 8 +- internal/mojang/textures_provider.go | 84 ++++++++++++++++++-- internal/mojang/textures_provider_test.go | 6 +- internal/mojang/uuids_provider.go | 67 +++++++++++++++- internal/mojang/uuids_provider_test.go | 5 +- internal/profiles/provider.go | 7 ++ internal/profiles/provider_test.go | 8 +- internal/utils/queue.go | 7 ++ internal/utils/queue_test.go | 9 +++ 19 files changed, 366 insertions(+), 102 deletions(-) create mode 100644 internal/di/httpClient.go diff --git a/go.mod b/go.mod index 2106628..eda6ba8 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.21 // Main dependencies require ( - github.com/SentimensRG/ctx v0.0.0-20180729130232-0bfd988c655d github.com/agoda-com/opentelemetry-go/otelslog v0.1.1 github.com/agoda-com/opentelemetry-logs-go v0.4.3 github.com/brunomvsouza/singleflight v0.4.0 @@ -21,6 +20,7 @@ require ( github.com/spf13/viper v1.18.1 github.com/valyala/fastjson v1.6.4 go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.48.0 + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 go.opentelemetry.io/contrib/instrumentation/runtime v0.48.0 go.opentelemetry.io/otel v1.23.1 go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1 @@ -29,6 +29,7 @@ require ( go.opentelemetry.io/otel/sdk v1.23.1 go.opentelemetry.io/otel/sdk/metric v1.23.1 go.opentelemetry.io/otel/trace v1.23.1 + go.uber.org/multierr v1.11.0 ) // Dev dependencies @@ -70,7 +71,6 @@ require ( github.com/tilinna/clock v1.0.2 // indirect go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1 // indirect go.opentelemetry.io/proto/otlp v1.1.0 // indirect - go.uber.org/multierr v1.11.0 // indirect golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect golang.org/x/net v0.21.0 // indirect diff --git a/go.sum b/go.sum index f53e131..58ab90d 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -github.com/SentimensRG/ctx v0.0.0-20180729130232-0bfd988c655d h1:CbB/Ef3TyBvSSJx2HDSUiw49ONTpaX6BGiI0jJEX6b8= -github.com/SentimensRG/ctx v0.0.0-20180729130232-0bfd988c655d/go.mod h1:cfn0Ycx1ASzCkl8+04zI4hrclf9YQ1QfncxzFiNtQLo= github.com/agoda-com/opentelemetry-go/otelslog v0.1.1 h1:6nV8PZCzySHuh9kP/HZ2OJqGucwQiM+yZRugKDvtzj4= github.com/agoda-com/opentelemetry-go/otelslog v0.1.1/go.mod h1:CSc0veIcY/HsIfH7l5PGtIpRvBttk09QUQlweVkD2PI= github.com/agoda-com/opentelemetry-logs-go v0.4.3 h1:dYAx/q9di+/Pv6HuGq59DFIOjqKT0LTy3PYTIz8ccq8= @@ -34,9 +32,6 @@ github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -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-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -51,8 +46,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= @@ -75,9 +68,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= -github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed h1:036IscGBfJsFIgJQzlui7nK1Ncm0tp2ktmPj8xO4N/0= -github.com/lufia/plan9stats v0.0.0-20231016141302-07b5767bb0ed/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mediocregopher/radix/v4 v4.1.4 h1:Uze6DEbEAvL+VHXUEu/EDBTkUk5CLct5h3nVSGpc6Ts= @@ -93,9 +83,6 @@ github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdU github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= -github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -103,11 +90,6 @@ github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6ke github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= -github.com/shirou/gopsutil/v3 v3.24.1 h1:R3t6ondCEvmARp3wxODhXMTLC/klMa87h2PHUw5m7QI= -github.com/shirou/gopsutil/v3 v3.24.1/go.mod h1:UU7a2MSBQa+kW1uuDq8DeEBS8kmrnQwsv2b5O513rwU= -github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= -github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= -github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= @@ -134,21 +116,12 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= github.com/tilinna/clock v1.0.2 h1:6BO2tyAC9JbPExKH/z9zl44FLu1lImh3nDNKA0kgrkI= github.com/tilinna/clock v1.0.2/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4= -github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4= -github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY= github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= -github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= -github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.48.0 h1:7rkdNoXgScpSUIqBch/VOB24fk9g0wl3Tr5WPtshi9o= go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.48.0/go.mod h1:U3t9uswWhDzieXHMNWP6zk87J4HNondiibKMdNLpnMk= -go.opentelemetry.io/contrib/instrumentation/host v0.48.0 h1:eVDLR/hletJcctz4rSWwb3QVzRnEQKuTVi6qAm7fsWs= -go.opentelemetry.io/contrib/instrumentation/host v0.48.0/go.mod h1:dWSGvPpaGKwBh/dpLJs6pczyOc82hBnxa1YTQZCic0I= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 h1:doUP+ExOpH3spVTLS0FcWGLnQrPct/hD/bCPbDRUEAU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA= go.opentelemetry.io/contrib/instrumentation/runtime v0.48.0 h1:dJlCKeq+zmO5Og4kgxqPvvJrzuD/mygs1g/NYM9dAsU= go.opentelemetry.io/contrib/instrumentation/runtime v0.48.0/go.mod h1:p+hpBCpLHpuUrR0lHgnHbUnbCBll1IhrcMIlycC+xYs= go.opentelemetry.io/otel v1.23.1 h1:Za4UzOqJYS+MUczKI320AtqZHZb7EqxO00jAHE0jmQY= @@ -181,12 +154,6 @@ golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= diff --git a/internal/di/di.go b/internal/di/di.go index 0e1b2cb..3b4b613 100644 --- a/internal/di/di.go +++ b/internal/di/di.go @@ -8,6 +8,7 @@ func New() (*di.Container, error) { contextDiOptions, dbDiOptions, handlersDiOptions, + httpClientDiOptions, loggerDiOptions, mojangDiOptions, profilesDiOptions, diff --git a/internal/di/httpClient.go b/internal/di/httpClient.go new file mode 100644 index 0000000..cff2546 --- /dev/null +++ b/internal/di/httpClient.go @@ -0,0 +1,18 @@ +package di + +import ( + "net/http" + + "github.com/defval/di" + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" +) + +var httpClientDiOptions = di.Options( + di.Provide(newHttpClient), +) + +func newHttpClient() *http.Client { + return &http.Client{ + Transport: otelhttp.NewTransport(http.DefaultTransport), + } +} diff --git a/internal/di/mojang.go b/internal/di/mojang.go index be73086..4c60dfe 100644 --- a/internal/di/mojang.go +++ b/internal/di/mojang.go @@ -21,7 +21,7 @@ var mojangDiOptions = di.Options( di.Provide(newMojangSignedTexturesProvider), ) -func newMojangApi(config *viper.Viper) (*mojang.MojangApi, error) { +func newMojangApi(config *viper.Viper, httpClient *http.Client) (*mojang.MojangApi, error) { batchUuidsUrl := config.GetString("mojang.batch_uuids_url") if batchUuidsUrl != "" { if _, err := url.ParseRequestURI(batchUuidsUrl); err != nil { @@ -36,8 +36,6 @@ func newMojangApi(config *viper.Viper) (*mojang.MojangApi, error) { } } - httpClient := &http.Client{} // TODO: extract to the singleton dependency - return mojang.NewMojangApi(httpClient, batchUuidsUrl, profileUrl), nil } @@ -62,21 +60,18 @@ func newMojangTexturesProviderFactory( func newMojangTexturesProvider( uuidsProvider mojang.UuidsProvider, texturesProvider mojang.TexturesProvider, -) *mojang.MojangTexturesProvider { - return &mojang.MojangTexturesProvider{ - UuidsProvider: uuidsProvider, - TexturesProvider: texturesProvider, - } +) (*mojang.MojangTexturesProvider, error) { + return mojang.NewMojangTexturesProvider( + uuidsProvider, + texturesProvider, + ) } func newMojangTexturesUuidsProviderFactory( batchProvider *mojang.BatchUuidsProvider, uuidsStorage mojang.MojangUuidsStorage, -) mojang.UuidsProvider { - return &mojang.UuidsProviderWithCache{ - Provider: batchProvider, - Storage: uuidsStorage, - } +) (mojang.UuidsProvider, error) { + return mojang.NewUuidsProviderWithCache(batchProvider, uuidsStorage) } func newMojangTexturesBatchUUIDsProvider( @@ -89,20 +84,19 @@ func newMojangTexturesBatchUUIDsProvider( // TODO: healthcheck is broken - uuidsProvider := mojang.NewBatchUuidsProvider( + return mojang.NewBatchUuidsProvider( mojangApi.UsernamesToUuids, config.GetInt("queue.batch_size"), config.GetDuration("queue.loop_delay"), config.GetString("queue.strategy") == "full-bus", ) - - return uuidsProvider, nil } -func newMojangSignedTexturesProvider(mojangApi *mojang.MojangApi) mojang.TexturesProvider { - return mojang.NewTexturesProviderWithInMemoryCache( - &mojang.MojangApiTexturesProvider{ - MojangApiTexturesEndpoint: mojangApi.UuidToTextures, - }, - ) +func newMojangSignedTexturesProvider(mojangApi *mojang.MojangApi) (mojang.TexturesProvider, error) { + provider, err := mojang.NewMojangApiTexturesProvider(mojangApi.UuidToTextures) + if err != nil { + return nil, err + } + + return mojang.NewTexturesProviderWithInMemoryCache(provider) } diff --git a/internal/di/profiles.go b/internal/di/profiles.go index 56c436c..623965f 100644 --- a/internal/di/profiles.go +++ b/internal/di/profiles.go @@ -19,9 +19,9 @@ func newProfilesManager(r profiles.ProfilesRepository) *profiles.Manager { func newProfilesProvider( finder profiles.ProfilesFinder, mojangProfilesProvider profiles.MojangProfilesProvider, -) *profiles.Provider { - return &profiles.Provider{ - ProfilesFinder: finder, - MojangProfilesProvider: mojangProfilesProvider, - } +) (*profiles.Provider, error) { + return profiles.NewProvider( + finder, + mojangProfilesProvider, + ) } diff --git a/internal/mojang/batch_uuids_provider.go b/internal/mojang/batch_uuids_provider.go index 4546454..a62e509 100644 --- a/internal/mojang/batch_uuids_provider.go +++ b/internal/mojang/batch_uuids_provider.go @@ -6,7 +6,9 @@ import ( "sync" "time" - "github.com/SentimensRG/ctx/mergectx" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/metric" + "go.uber.org/multierr" "ely.by/chrly/internal/utils" ) @@ -23,6 +25,7 @@ type BatchUuidsProvider struct { fireChan chan any stopChan chan any onFirstCall sync.Once + metrics *batchUuidsProviderMetrics } func NewBatchUuidsProvider( @@ -30,22 +33,31 @@ func NewBatchUuidsProvider( batchSize int, awaitDelay time.Duration, fireOnFull bool, -) *BatchUuidsProvider { +) (*BatchUuidsProvider, error) { + queue := utils.NewQueue[*job]() + + metrics, err := newBatchUuidsProviderMetrics(otel.GetMeterProvider().Meter(ScopeName), queue) + if err != nil { + return nil, err + } + return &BatchUuidsProvider{ UsernamesToUuidsEndpoint: endpoint, stopChan: make(chan any), batch: batchSize, delay: awaitDelay, fireOnFull: fireOnFull, - queue: utils.NewQueue[*job](), + queue: queue, fireChan: make(chan any), - } + metrics: metrics, + }, nil } type job struct { - Username string - Ctx context.Context - ResultChan chan<- *jobResult + Username string + Ctx context.Context + QueuingTime time.Time + ResultChan chan<- *jobResult } type jobResult struct { @@ -55,7 +67,7 @@ type jobResult struct { func (p *BatchUuidsProvider) GetUuid(ctx context.Context, username string) (*ProfileInfo, error) { resultChan := make(chan *jobResult) - n := p.queue.Enqueue(&job{username, ctx, resultChan}) + n := p.queue.Enqueue(&job{username, ctx, time.Now(), resultChan}) if p.fireOnFull && n%p.batch == 0 { p.fireChan <- struct{}{} } @@ -92,11 +104,14 @@ func (p *BatchUuidsProvider) startQueue() { } func (p *BatchUuidsProvider) fireRequest() { + // Since this method is an aggregator, it uses its own context to manage its lifetime + reqCtx := context.Background() jobs := make([]*job, 0, p.batch) n := p.batch for { foundJobs, left := p.queue.Dequeue(n) for i := range foundJobs { + p.metrics.QueueTime.Record(reqCtx, float64(time.Since(foundJobs[i].QueuingTime))) if foundJobs[i].Ctx.Err() != nil { // If the job context has already ended, its result will be returned in the GetUuid method close(foundJobs[i].ResultChan) @@ -119,14 +134,14 @@ func (p *BatchUuidsProvider) fireRequest() { return } - ctx := context.Background() usernames := make([]string, len(jobs)) for i, job := range jobs { usernames[i] = job.Username - ctx = mergectx.Join(ctx, job.Ctx) } - profiles, err := p.UsernamesToUuidsEndpoint(ctx, usernames) + p.metrics.BatchSize.Record(reqCtx, int64(len(usernames))) + + profiles, err := p.UsernamesToUuidsEndpoint(reqCtx, usernames) for _, job := range jobs { response := &jobResult{} if err == nil { @@ -145,3 +160,39 @@ func (p *BatchUuidsProvider) fireRequest() { close(job.ResultChan) } } + +func newBatchUuidsProviderMetrics(meter metric.Meter, queue *utils.Queue[*job]) (*batchUuidsProviderMetrics, error) { + m := &batchUuidsProviderMetrics{} + var errors, err error + + m.QueueLength, err = meter.Int64ObservableGauge( + "queue.length", // TODO: look for better naming + metric.WithDescription(""), // TODO: description + metric.WithInt64Callback(func(_ context.Context, o metric.Int64Observer) error { + o.Observe(int64(queue.Len())) + return nil + }), + ) + errors = multierr.Append(errors, err) + + m.QueueTime, err = meter.Float64Histogram( + "queue.duration", + metric.WithDescription(""), // TODO: description + metric.WithUnit("ms"), + ) + + m.BatchSize, err = meter.Int64Histogram( + "batch.size", + metric.WithDescription(""), // TODO: write description + metric.WithUnit("1"), + ) + errors = multierr.Append(errors, err) + + return m, errors +} + +type batchUuidsProviderMetrics struct { + QueueLength metric.Int64ObservableGauge + QueueTime metric.Float64Histogram + BatchSize metric.Int64Histogram +} diff --git a/internal/mojang/batch_uuids_provider_test.go b/internal/mojang/batch_uuids_provider_test.go index cda1fca..308f4b6 100644 --- a/internal/mojang/batch_uuids_provider_test.go +++ b/internal/mojang/batch_uuids_provider_test.go @@ -41,7 +41,7 @@ type batchUuidsProviderTestSuite struct { func (s *batchUuidsProviderTestSuite) SetupTest() { s.MojangApi = &mojangUsernamesToUuidsRequestMock{} - s.Provider = NewBatchUuidsProvider( + s.Provider, _ = NewBatchUuidsProvider( s.MojangApi.UsernamesToUuids, 3, awaitDelay, diff --git a/internal/mojang/client.go b/internal/mojang/client.go index 65cc28e..f9c7e4b 100644 --- a/internal/mojang/client.go +++ b/internal/mojang/client.go @@ -77,6 +77,7 @@ func (c *MojangApi) UsernamesToUuids(ctx context.Context, usernames []string) ([ // Obtains textures information for provided uuid // See https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape func (c *MojangApi) UuidToTextures(ctx context.Context, uuid string, signed bool) (*ProfileResponse, error) { + // TODO: normalize request url for tracing normalizedUuid := strings.ReplaceAll(uuid, "-", "") url := c.profileUrl + normalizedUuid if signed { diff --git a/internal/mojang/provider.go b/internal/mojang/provider.go index c9b84d4..68d4ac0 100644 --- a/internal/mojang/provider.go +++ b/internal/mojang/provider.go @@ -7,8 +7,13 @@ import ( "strings" "github.com/brunomvsouza/singleflight" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/metric" + "go.uber.org/multierr" ) +const ScopeName = "ely.by/chrly/internal/mojang" + var InvalidUsername = errors.New("the username passed doesn't meet Mojang's requirements") // https://help.minecraft.net/hc/en-us/articles/4408950195341#h_01GE5JX1Z0CZ833A7S54Y195KV @@ -22,11 +27,28 @@ type TexturesProvider interface { GetTextures(ctx context.Context, uuid string) (*ProfileResponse, error) } +func NewMojangTexturesProvider( + uuidsProvider UuidsProvider, + texturesProvider TexturesProvider, +) (*MojangTexturesProvider, error) { + meter, err := newProviderMetrics(otel.GetMeterProvider().Meter(ScopeName)) + if err != nil { + return nil, err + } + + return &MojangTexturesProvider{ + UuidsProvider: uuidsProvider, + TexturesProvider: texturesProvider, + metrics: meter, + }, nil +} + type MojangTexturesProvider struct { UuidsProvider TexturesProvider - group singleflight.Group[string, *ProfileResponse] + metrics *providerMetrics + group singleflight.Group[string, *ProfileResponse] } func (p *MojangTexturesProvider) GetForUsername(ctx context.Context, username string) (*ProfileResponse, error) { @@ -36,7 +58,7 @@ func (p *MojangTexturesProvider) GetForUsername(ctx context.Context, username st username = strings.ToLower(username) - result, err, _ := p.group.Do(username, func() (*ProfileResponse, error) { + result, err, shared := p.group.Do(username, func() (*ProfileResponse, error) { profile, err := p.UuidsProvider.GetUuid(ctx, username) if err != nil { return nil, err @@ -49,12 +71,69 @@ func (p *MojangTexturesProvider) GetForUsername(ctx context.Context, username st return p.TexturesProvider.GetTextures(ctx, profile.Id) }) + p.recordMetrics(ctx, shared, result, err) + return result, err } +func (p *MojangTexturesProvider) recordMetrics(ctx context.Context, shared bool, result *ProfileResponse, err error) { + if shared { + p.metrics.Shared.Add(ctx, 1) + } + + if err != nil { + p.metrics.Failed.Add(ctx, 1) + return + } + + if result != nil { + p.metrics.Found.Add(ctx, 1) + } else { + p.metrics.Missed.Add(ctx, 1) + } +} + type NilProvider struct { } func (*NilProvider) GetForUsername(ctx context.Context, username string) (*ProfileResponse, error) { return nil, nil } + +func newProviderMetrics(meter metric.Meter) (*providerMetrics, error) { + m := &providerMetrics{} + var errors, err error + + m.Found, err = meter.Int64Counter( + "results.found", + metric.WithDescription(""), // TODO: description + ) + errors = multierr.Append(errors, err) + + m.Missed, err = meter.Int64Counter( + "results.missed", + metric.WithDescription(""), // TODO: description + ) + errors = multierr.Append(errors, err) + + m.Failed, err = meter.Int64Counter( + "results.failed", + metric.WithDescription(""), // TODO: description + ) + errors = multierr.Append(errors, err) + + m.Shared, err = meter.Int64Counter( + "singleflight.shared", + metric.WithDescription(""), // TODO: description + ) + errors = multierr.Append(errors, err) + + return m, errors +} + +type providerMetrics struct { + Found metric.Int64Counter + Missed metric.Int64Counter + Failed metric.Int64Counter + Shared metric.Int64Counter +} diff --git a/internal/mojang/provider_test.go b/internal/mojang/provider_test.go index 3f78626..ea3b8ef 100644 --- a/internal/mojang/provider_test.go +++ b/internal/mojang/provider_test.go @@ -51,10 +51,10 @@ func (s *providerTestSuite) SetupTest() { s.UuidsProvider = &mockUuidsProvider{} s.TexturesProvider = &TexturesProviderMock{} - s.Provider = &MojangTexturesProvider{ - UuidsProvider: s.UuidsProvider, - TexturesProvider: s.TexturesProvider, - } + s.Provider, _ = NewMojangTexturesProvider( + s.UuidsProvider, + s.TexturesProvider, + ) } func (s *providerTestSuite) TearDownTest() { diff --git a/internal/mojang/textures_provider.go b/internal/mojang/textures_provider.go index 2257e76..85c4d20 100644 --- a/internal/mojang/textures_provider.go +++ b/internal/mojang/textures_provider.go @@ -6,13 +6,33 @@ import ( "time" "github.com/jellydator/ttlcache/v3" + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/metric" + "go.uber.org/multierr" ) +type MojangApiTexturesProviderFunc func(ctx context.Context, uuid string, signed bool) (*ProfileResponse, error) + +func NewMojangApiTexturesProvider(endpoint MojangApiTexturesProviderFunc) (*MojangApiTexturesProvider, error) { + metrics, err := newMojangApiTexturesProviderMetrics(otel.GetMeterProvider().Meter(ScopeName)) + if err != nil { + return nil, err + } + + return &MojangApiTexturesProvider{ + MojangApiTexturesEndpoint: endpoint, + metrics: metrics, + }, nil +} + type MojangApiTexturesProvider struct { - MojangApiTexturesEndpoint func(ctx context.Context, uuid string, signed bool) (*ProfileResponse, error) + MojangApiTexturesEndpoint MojangApiTexturesProviderFunc + metrics *mojangApiTexturesProviderMetrics } func (p *MojangApiTexturesProvider) GetTextures(ctx context.Context, uuid string) (*ProfileResponse, error) { + p.metrics.Requests.Add(ctx, 1) + return p.MojangApiTexturesEndpoint(ctx, uuid, true) } @@ -22,27 +42,35 @@ type TexturesProviderWithInMemoryCache struct { provider TexturesProvider once sync.Once cache *ttlcache.Cache[string, *ProfileResponse] + metrics *texturesProviderWithInMemoryCacheMetrics } -func NewTexturesProviderWithInMemoryCache(provider TexturesProvider) *TexturesProviderWithInMemoryCache { - storage := &TexturesProviderWithInMemoryCache{ +func NewTexturesProviderWithInMemoryCache(provider TexturesProvider) (*TexturesProviderWithInMemoryCache, error) { + metrics, err := newTexturesProviderWithInMemoryCacheMetrics(otel.GetMeterProvider().Meter(ScopeName)) + if err != nil { + return nil, err + } + + return &TexturesProviderWithInMemoryCache{ provider: provider, cache: ttlcache.New[string, *ProfileResponse]( ttlcache.WithDisableTouchOnHit[string, *ProfileResponse](), // I'm aware of ttlcache.WithLoader(), but it doesn't allow to return an error ), - } - - return storage + metrics: metrics, + }, nil } func (s *TexturesProviderWithInMemoryCache) GetTextures(ctx context.Context, uuid string) (*ProfileResponse, error) { item := s.cache.Get(uuid) // Don't check item.IsExpired() since Get function is already did this check if item != nil { + s.metrics.Hits.Add(ctx, 1) return item.Value(), nil } + s.metrics.Misses.Add(ctx, 1) + result, err := s.provider.GetTextures(ctx, uuid) if err != nil { return nil, err @@ -66,3 +94,47 @@ func (s *TexturesProviderWithInMemoryCache) startGcOnce() { go s.cache.Start() }) } + +func newMojangApiTexturesProviderMetrics(meter metric.Meter) (*mojangApiTexturesProviderMetrics, error) { + m := &mojangApiTexturesProviderMetrics{} + var errors, err error + + m.Requests, err = meter.Int64Counter( + "textures.requests", + metric.WithDescription(""), // TODO: write description + metric.WithUnit("1"), + ) + errors = multierr.Append(errors, err) + + return m, errors +} + +type mojangApiTexturesProviderMetrics struct { + Requests metric.Int64Counter +} + +func newTexturesProviderWithInMemoryCacheMetrics(meter metric.Meter) (*texturesProviderWithInMemoryCacheMetrics, error) { + m := &texturesProviderWithInMemoryCacheMetrics{} + var errors, err error + + m.Hits, err = meter.Int64Counter( + "textures.cache.hit", + metric.WithDescription(""), // TODO: write description + metric.WithUnit("1"), + ) + errors = multierr.Append(errors, err) + + m.Misses, err = meter.Int64Counter( + "textures.cache.miss", + metric.WithDescription(""), // TODO: write description + metric.WithUnit("1"), + ) + errors = multierr.Append(errors, err) + + return m, errors +} + +type texturesProviderWithInMemoryCacheMetrics struct { + Hits metric.Int64Counter + Misses metric.Int64Counter +} diff --git a/internal/mojang/textures_provider_test.go b/internal/mojang/textures_provider_test.go index c67d303..6f48dbf 100644 --- a/internal/mojang/textures_provider_test.go +++ b/internal/mojang/textures_provider_test.go @@ -53,9 +53,7 @@ type MojangApiTexturesProviderSuite struct { func (s *MojangApiTexturesProviderSuite) SetupTest() { s.MojangApi = &MojangUuidToTexturesRequestMock{} - s.Provider = &MojangApiTexturesProvider{ - MojangApiTexturesEndpoint: s.MojangApi.UuidToTextures, - } + s.Provider, _ = NewMojangApiTexturesProvider(s.MojangApi.UuidToTextures) } func (s *MojangApiTexturesProviderSuite) TearDownTest() { @@ -95,7 +93,7 @@ type TexturesProviderWithInMemoryCacheSuite struct { func (s *TexturesProviderWithInMemoryCacheSuite) SetupTest() { s.Original = &TexturesProviderMock{} - s.Provider = NewTexturesProviderWithInMemoryCache(s.Original) + s.Provider, _ = NewTexturesProviderWithInMemoryCache(s.Original) } func (s *TexturesProviderWithInMemoryCacheSuite) TearDownTest() { diff --git a/internal/mojang/uuids_provider.go b/internal/mojang/uuids_provider.go index c2e957a..61ddfa2 100644 --- a/internal/mojang/uuids_provider.go +++ b/internal/mojang/uuids_provider.go @@ -1,6 +1,12 @@ package mojang -import "context" +import ( + "context" + + "go.opentelemetry.io/otel" + "go.opentelemetry.io/otel/metric" + "go.uber.org/multierr" +) type MojangUuidsStorage interface { // The second argument must be returned as a incoming username in case, @@ -10,13 +16,32 @@ type MojangUuidsStorage interface { StoreMojangUuid(ctx context.Context, username string, uuid string) error } +func NewUuidsProviderWithCache(o UuidsProvider, s MojangUuidsStorage) (*UuidsProviderWithCache, error) { + metrics, err := newUuidsProviderWithCacheMetrics(otel.GetMeterProvider().Meter(ScopeName)) + if err != nil { + return nil, err + } + + return &UuidsProviderWithCache{ + Provider: o, + Storage: s, + metrics: metrics, + }, nil +} + type UuidsProviderWithCache struct { Provider UuidsProvider Storage MojangUuidsStorage + + metrics *uuidsProviderWithCacheMetrics } func (p *UuidsProviderWithCache) GetUuid(ctx context.Context, username string) (*ProfileInfo, error) { - uuid, foundUsername, err := p.Storage.GetUuidForMojangUsername(ctx, username) + var uuid, foundUsername string + var err error + defer p.recordMetrics(ctx, uuid, foundUsername, err) + + uuid, foundUsername, err = p.Storage.GetUuidForMojangUsername(ctx, username) if err != nil { return nil, err } @@ -45,3 +70,41 @@ func (p *UuidsProviderWithCache) GetUuid(ctx context.Context, username string) ( return profile, nil } + +func (p *UuidsProviderWithCache) recordMetrics(ctx context.Context, uuid string, username string, err error) { + if err != nil { + return + } + + if username != "" { + p.metrics.Hits.Add(ctx, 1) + } else { + p.metrics.Misses.Add(ctx, 1) + } +} + +func newUuidsProviderWithCacheMetrics(meter metric.Meter) (*uuidsProviderWithCacheMetrics, error) { + m := &uuidsProviderWithCacheMetrics{} + var errors, err error + + m.Hits, err = meter.Int64Counter( + "uuids.cache.hit", + metric.WithDescription(""), // TODO: write description + metric.WithUnit("1"), + ) + errors = multierr.Append(errors, err) + + m.Misses, err = meter.Int64Counter( + "uuids.cache.miss", + metric.WithDescription(""), // TODO: write description + metric.WithUnit("1"), + ) + errors = multierr.Append(errors, err) + + return m, errors +} + +type uuidsProviderWithCacheMetrics struct { + Hits metric.Int64Counter + Misses metric.Int64Counter +} diff --git a/internal/mojang/uuids_provider_test.go b/internal/mojang/uuids_provider_test.go index 69d283f..6c157a0 100644 --- a/internal/mojang/uuids_provider_test.go +++ b/internal/mojang/uuids_provider_test.go @@ -50,10 +50,7 @@ type UuidsProviderWithCacheSuite struct { func (s *UuidsProviderWithCacheSuite) SetupTest() { s.Original = &UuidsProviderMock{} s.Storage = &MojangUuidsStorageMock{} - s.Provider = &UuidsProviderWithCache{ - Provider: s.Original, - Storage: s.Storage, - } + s.Provider, _ = NewUuidsProviderWithCache(s.Original, s.Storage) } func (s *UuidsProviderWithCacheSuite) TearDownTest() { diff --git a/internal/profiles/provider.go b/internal/profiles/provider.go index 4a157af..745bf1d 100644 --- a/internal/profiles/provider.go +++ b/internal/profiles/provider.go @@ -16,6 +16,13 @@ type MojangProfilesProvider interface { GetForUsername(ctx context.Context, username string) (*mojang.ProfileResponse, error) } +func NewProvider(pf ProfilesFinder, mpf MojangProfilesProvider) (*Provider, error) { + return &Provider{ + ProfilesFinder: pf, + MojangProfilesProvider: mpf, + }, nil +} + type Provider struct { ProfilesFinder MojangProfilesProvider diff --git a/internal/profiles/provider_test.go b/internal/profiles/provider_test.go index 9158dc8..788ba2a 100644 --- a/internal/profiles/provider_test.go +++ b/internal/profiles/provider_test.go @@ -54,10 +54,10 @@ type CombinedProfilesProviderSuite struct { func (t *CombinedProfilesProviderSuite) SetupSubTest() { t.ProfilesFinder = &ProfilesFinderMock{} t.MojangProfilesProvider = &MojangProfilesProviderMock{} - t.Provider = &Provider{ - ProfilesFinder: t.ProfilesFinder, - MojangProfilesProvider: t.MojangProfilesProvider, - } + t.Provider, _ = NewProvider( + t.ProfilesFinder, + t.MojangProfilesProvider, + ) } func (t *CombinedProfilesProviderSuite) TearDownSubTest() { diff --git a/internal/utils/queue.go b/internal/utils/queue.go index 23e5b2e..1ad9c76 100644 --- a/internal/utils/queue.go +++ b/internal/utils/queue.go @@ -38,3 +38,10 @@ func (s *Queue[T]) Dequeue(n int) ([]T, int) { return items, l - n } + +func (s *Queue[T]) Len() int { + s.lock.Lock() + defer s.lock.Unlock() + + return len(s.items) +} diff --git a/internal/utils/queue_test.go b/internal/utils/queue_test.go index 9701f75..4bd2b88 100644 --- a/internal/utils/queue_test.go +++ b/internal/utils/queue_test.go @@ -35,4 +35,13 @@ func TestQueue(t *testing.T) { require.Equal(t, "username4", items[1]) require.Equal(t, "username5", items[2]) }) + + t.Run("Len", func(t *testing.T) { + s := NewQueue[string]() + s.Enqueue("username1") + s.Enqueue("username2") + s.Enqueue("username3") + + require.Equal(t, 3, s.Len()) + }) } From b9a38dd947b95adc9d5df58e21d32b4085ae09e0 Mon Sep 17 00:00:00 2001 From: ErickSkrauch Date: Tue, 5 Mar 2024 15:14:10 +0100 Subject: [PATCH 3/3] Add autoconfiguration for OTEL and resolve TODOs for metrics --- go.mod | 32 +++++++--- go.sum | 68 +++++++++++++------- internal/cmd/serve.go | 24 +++---- internal/di/httpClient.go | 5 +- internal/di/mojang.go | 2 - internal/mojang/batch_uuids_provider.go | 34 ++++++---- internal/mojang/client.go | 1 - internal/mojang/provider.go | 84 +++++++++++++++++-------- internal/mojang/textures_provider.go | 8 +-- internal/mojang/uuids_provider.go | 4 +- internal/otel/setup.go | 38 ++++------- 11 files changed, 180 insertions(+), 120 deletions(-) diff --git a/go.mod b/go.mod index eda6ba8..720d03a 100644 --- a/go.mod +++ b/go.mod @@ -19,16 +19,13 @@ require ( github.com/spf13/cobra v1.8.0 github.com/spf13/viper v1.18.1 github.com/valyala/fastjson v1.6.4 + go.opentelemetry.io/contrib/exporters/autoexport v0.49.0 go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.48.0 - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 go.opentelemetry.io/contrib/instrumentation/runtime v0.48.0 - go.opentelemetry.io/otel v1.23.1 - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1 - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.23.1 - go.opentelemetry.io/otel/metric v1.23.1 - go.opentelemetry.io/otel/sdk v1.23.1 - go.opentelemetry.io/otel/sdk/metric v1.23.1 - go.opentelemetry.io/otel/trace v1.23.1 + go.opentelemetry.io/otel v1.24.0 + go.opentelemetry.io/otel/metric v1.24.0 + go.opentelemetry.io/otel/sdk v1.24.0 + go.opentelemetry.io/otel/sdk/metric v1.24.0 go.uber.org/multierr v1.11.0 ) @@ -40,8 +37,10 @@ require ( // Indirect dependencies require ( + github.com/beorn7/perks v1.0.1 // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect @@ -57,9 +56,14 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/magiconair/properties v1.8.7 // indirect + github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/pelletier/go-toml/v2 v2.1.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_golang v1.18.0 // indirect + github.com/prometheus/client_model v0.6.0 // indirect + github.com/prometheus/common v0.45.0 // indirect + github.com/prometheus/procfs v0.12.0 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -69,7 +73,15 @@ require ( github.com/stretchr/objx v0.5.0 // indirect github.com/subosito/gotenv v1.6.0 // indirect github.com/tilinna/clock v1.0.2 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.46.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.24.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 // indirect + go.opentelemetry.io/otel/trace v1.24.0 // indirect go.opentelemetry.io/proto/otlp v1.1.0 // indirect golang.org/x/crypto v0.19.0 // indirect golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb // indirect @@ -79,7 +91,7 @@ require ( golang.org/x/text v0.14.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014 // indirect - google.golang.org/grpc v1.61.0 // indirect + google.golang.org/grpc v1.61.1 // indirect google.golang.org/protobuf v1.32.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 58ab90d..683e2e2 100644 --- a/go.sum +++ b/go.sum @@ -2,12 +2,16 @@ github.com/agoda-com/opentelemetry-go/otelslog v0.1.1 h1:6nV8PZCzySHuh9kP/HZ2OJq github.com/agoda-com/opentelemetry-go/otelslog v0.1.1/go.mod h1:CSc0veIcY/HsIfH7l5PGtIpRvBttk09QUQlweVkD2PI= github.com/agoda-com/opentelemetry-logs-go v0.4.3 h1:dYAx/q9di+/Pv6HuGq59DFIOjqKT0LTy3PYTIz8ccq8= github.com/agoda-com/opentelemetry-logs-go v0.4.3/go.mod h1:gPQ0fHqroxNP2DlQFZt29/pfqGiP2m6Q5CCxEgLo6yQ= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/brunomvsouza/singleflight v0.4.0 h1:9dNcTeYoXSus3xbZEM0EEZ11EcCRjUZOvVW8rnDMG5Y= github.com/brunomvsouza/singleflight v0.4.0/go.mod h1:8RYo9j5WQRupmsnUz5DlUWZxDLNi+t9Zhj3EZFmns7I= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV47EEXL8mWmRdEfGscSJ+7EgePNgt0s= github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -70,6 +74,8 @@ github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= +github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/mediocregopher/radix/v4 v4.1.4 h1:Uze6DEbEAvL+VHXUEu/EDBTkUk5CLct5h3nVSGpc6Ts= github.com/mediocregopher/radix/v4 v4.1.4/go.mod h1:ajchozX/6ELmydxWeWM6xCFHVpZ4+67LXHOTOVR0nCE= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= @@ -83,6 +89,14 @@ github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdU github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= +github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= +github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= +github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= +github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= +github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= +github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -118,32 +132,42 @@ github.com/tilinna/clock v1.0.2 h1:6BO2tyAC9JbPExKH/z9zl44FLu1lImh3nDNKA0kgrkI= github.com/tilinna/clock v1.0.2/go.mod h1:ZsP7BcY7sEEz7ktc0IVy8Us6boDrK8VradlKRUGfOao= github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXVQ= github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= +go.opentelemetry.io/contrib/exporters/autoexport v0.49.0 h1:SPuRs5SgCd9loXBBY5HuZsyuweowIs6ADg9UtStEv+k= +go.opentelemetry.io/contrib/exporters/autoexport v0.49.0/go.mod h1:BDsrww+PTgwfvBjsZQMstsE1n5dS3hDCtAfYG1t3wag= go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.48.0 h1:7rkdNoXgScpSUIqBch/VOB24fk9g0wl3Tr5WPtshi9o= go.opentelemetry.io/contrib/instrumentation/github.com/gorilla/mux/otelmux v0.48.0/go.mod h1:U3t9uswWhDzieXHMNWP6zk87J4HNondiibKMdNLpnMk= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 h1:doUP+ExOpH3spVTLS0FcWGLnQrPct/hD/bCPbDRUEAU= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA= go.opentelemetry.io/contrib/instrumentation/runtime v0.48.0 h1:dJlCKeq+zmO5Og4kgxqPvvJrzuD/mygs1g/NYM9dAsU= go.opentelemetry.io/contrib/instrumentation/runtime v0.48.0/go.mod h1:p+hpBCpLHpuUrR0lHgnHbUnbCBll1IhrcMIlycC+xYs= -go.opentelemetry.io/otel v1.23.1 h1:Za4UzOqJYS+MUczKI320AtqZHZb7EqxO00jAHE0jmQY= -go.opentelemetry.io/otel v1.23.1/go.mod h1:Td0134eafDLcTS4y+zQ26GE8u3dEuRBiBCTUIRHaikA= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1 h1:q/Nj5/2TZRIt6PderQ9oU0M00fzoe8UZuINGw6ETGTw= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.23.1/go.mod h1:DTE9yAu6r08jU3xa68GiSeI7oRcSEQ2RpKbbQGO+dWM= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1 h1:o8iWeVFa1BcLtVEV0LzrCxV2/55tB3xLxADr6Kyoey4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.23.1/go.mod h1:SEVfdK4IoBnbT2FXNM/k8yC08MrfbhWk3U4ljM8B3HE= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.23.1 h1:cfuy3bXmLJS7M1RZmAL6SuhGtKUp2KEsrm00OlAXkq4= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.23.1/go.mod h1:22jr92C6KwlwItJmQzfixzQM3oyyuYLCfHiMY+rpsPU= -go.opentelemetry.io/otel/metric v1.23.1 h1:PQJmqJ9u2QaJLBOELl1cxIdPcpbwzbkjfEyelTl2rlo= -go.opentelemetry.io/otel/metric v1.23.1/go.mod h1:mpG2QPlAfnK8yNhNJAxDZruU9Y1/HubbC+KyH8FaCWI= -go.opentelemetry.io/otel/sdk v1.23.1 h1:O7JmZw0h76if63LQdsBMKQDWNb5oEcOThG9IrxscV+E= -go.opentelemetry.io/otel/sdk v1.23.1/go.mod h1:LzdEVR5am1uKOOwfBWFef2DCi1nu3SA8XQxx2IerWFk= -go.opentelemetry.io/otel/sdk/metric v1.23.1 h1:T9/8WsYg+ZqIpMWwdISVVrlGb/N0Jr1OHjR/alpKwzg= -go.opentelemetry.io/otel/sdk/metric v1.23.1/go.mod h1:8WX6WnNtHCgUruJ4TJ+UssQjMtpxkpX0zveQC8JG/E0= -go.opentelemetry.io/otel/trace v1.23.1 h1:4LrmmEd8AU2rFvU1zegmvqW7+kWarxtNOPyeL6HmYY8= -go.opentelemetry.io/otel/trace v1.23.1/go.mod h1:4IpnpJFwr1mo/6HL8XIPJaE9y0+u1KcVmuW7dwFSVrI= +go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo= +go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0 h1:f2jriWfOdldanBwS9jNBdeOKAQN7b4ugAMaNu1/1k9g= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.24.0/go.mod h1:B+bcQI1yTY+N0vqMpoZbEN7+XU4tNM0DmUiOwebFJWI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0 h1:mM8nKi6/iFQ0iqst80wDHU2ge198Ye/TfN0WBS5U24Y= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.24.0/go.mod h1:0PrIIzDteLSmNyxqcGYRL4mDIo8OTuBAOI/Bn1URxac= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0 h1:t6wl9SPayj+c7lEIFgm4ooDBZVb01IhLB4InpomhRw8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.24.0/go.mod h1:iSDOcsnSA5INXzZtwaBPrKp/lWu/V14Dd+llD0oI2EA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0 h1:Mw5xcxMwlqoJd97vwPxA8isEaIoxsta9/Q51+TTJLGE= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.24.0/go.mod h1:CQNu9bj7o7mC6U7+CA/schKEYakYXWr79ucDHTMGhCM= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0 h1:Xw8U6u2f8DK2XAkGRFV7BBLENgnTGX9i4rQRxJf+/vs= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.24.0/go.mod h1:6KW1Fm6R/s6Z3PGXwSJN2K4eT6wQB3vXX6CVnYX9NmM= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0 h1:I8WIFXR351FoLJYuloU4EgXbtNX2URfU/85pUPheIEQ= +go.opentelemetry.io/otel/exporters/prometheus v0.46.0/go.mod h1:ztwVUHe5DTR/1v7PeuGRnU5Bbd4QKYwApWmuutKsJSs= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.24.0 h1:JYE2HM7pZbOt5Jhk8ndWZTUWYOVift2cHjXVMkPdmdc= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.24.0/go.mod h1:yMb/8c6hVsnma0RpsBMNo0fEiQKeclawtgaIaOp2MLY= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0 h1:s0PHtIkN+3xrbDOpt2M8OTG92cWqUESvzh2MxiR5xY8= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.24.0/go.mod h1:hZlFbDbRt++MMPCCfSJfmhkGIWnX1h3XjkfxZUjLrIA= +go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI= +go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= +go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= +go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= +go.opentelemetry.io/otel/sdk/metric v1.24.0 h1:yyMQrPzF+k88/DbH7o4FMAs80puqd+9osbiBrJrz/w8= +go.opentelemetry.io/otel/sdk/metric v1.24.0/go.mod h1:I6Y5FjH6rvEnTTAYQz3Mmv2kl6Ek5IIrmwTLqMrrOE0= +go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI= +go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI= go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= @@ -165,8 +189,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014 h1: google.golang.org/genproto/googleapis/api v0.0.0-20240205150955-31a09d347014/go.mod h1:rbHMSEDyoYX62nRVLOCc4Qt1HbsdytAYoVwgjiOhF3I= google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014 h1:FSL3lRCkhaPFxqi0s9o+V4UI2WTzAVOvkgbd4kVV4Wg= google.golang.org/genproto/googleapis/rpc v0.0.0-20240205150955-31a09d347014/go.mod h1:SaPjaZGWb0lPqs6Ittu0spdfrOArqji4ZdeP5IC/9N4= -google.golang.org/grpc v1.61.0 h1:TOvOcuXn30kRao+gfcvsebNEa5iZIiLkisYEkf7R7o0= -google.golang.org/grpc v1.61.0/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= +google.golang.org/grpc v1.61.1 h1:kLAiWrZs7YeDM6MumDe7m3y4aM6wacLzM1Y/wiLP9XY= +google.golang.org/grpc v1.61.1/go.mod h1:VUbo7IFqmF1QtCAstipjG0GIoq49KvMe9+h1jFLBNJs= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= diff --git a/internal/cmd/serve.go b/internal/cmd/serve.go index 8eda6d1..83de9e6 100644 --- a/internal/cmd/serve.go +++ b/internal/cmd/serve.go @@ -33,23 +33,25 @@ func startServer(modules ...string) error { return err } - shutdownOtel, err := otel.SetupOTelSDK(globalCtx) - defer func() { - err := shutdownOtel(context.Background()) - if err != nil { - slog.Error("Unable to shutdown OpenTelemetry", slog.Any("error", err)) - } - }() - if err != nil { - return err - } - var config *viper.Viper err = container.Resolve(&config) if err != nil { return err } + if !config.GetBool("otel.sdk.disabled") { + shutdownOtel, err := otel.SetupOTelSDK(globalCtx) + defer func() { + err := shutdownOtel(context.Background()) + if err != nil { + slog.Error("Unable to shutdown OpenTelemetry", slog.Any("error", err)) + } + }() + if err != nil { + return err + } + } + config.Set("modules", modules) err = container.Invoke(http.StartServer) diff --git a/internal/di/httpClient.go b/internal/di/httpClient.go index cff2546..1bb2f66 100644 --- a/internal/di/httpClient.go +++ b/internal/di/httpClient.go @@ -4,7 +4,6 @@ import ( "net/http" "github.com/defval/di" - "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" ) var httpClientDiOptions = di.Options( @@ -12,7 +11,5 @@ var httpClientDiOptions = di.Options( ) func newHttpClient() *http.Client { - return &http.Client{ - Transport: otelhttp.NewTransport(http.DefaultTransport), - } + return &http.Client{} } diff --git a/internal/di/mojang.go b/internal/di/mojang.go index 4c60dfe..0a96d0e 100644 --- a/internal/di/mojang.go +++ b/internal/di/mojang.go @@ -82,8 +82,6 @@ func newMojangTexturesBatchUUIDsProvider( config.SetDefault("queue.batch_size", 10) config.SetDefault("queue.strategy", "periodic") - // TODO: healthcheck is broken - return mojang.NewBatchUuidsProvider( mojangApi.UsernamesToUuids, config.GetInt("queue.batch_size"), diff --git a/internal/mojang/batch_uuids_provider.go b/internal/mojang/batch_uuids_provider.go index a62e509..4e51ecc 100644 --- a/internal/mojang/batch_uuids_provider.go +++ b/internal/mojang/batch_uuids_provider.go @@ -111,7 +111,7 @@ func (p *BatchUuidsProvider) fireRequest() { for { foundJobs, left := p.queue.Dequeue(n) for i := range foundJobs { - p.metrics.QueueTime.Record(reqCtx, float64(time.Since(foundJobs[i].QueuingTime))) + p.metrics.QueueTime.Record(reqCtx, float64(time.Since(foundJobs[i].QueuingTime).Milliseconds())) if foundJobs[i].Ctx.Err() != nil { // If the job context has already ended, its result will be returned in the GetUuid method close(foundJobs[i].ResultChan) @@ -139,6 +139,7 @@ func (p *BatchUuidsProvider) fireRequest() { usernames[i] = job.Username } + p.metrics.Requests.Add(reqCtx, 1) p.metrics.BatchSize.Record(reqCtx, int64(len(usernames))) profiles, err := p.UsernamesToUuidsEndpoint(reqCtx, usernames) @@ -165,9 +166,23 @@ func newBatchUuidsProviderMetrics(meter metric.Meter, queue *utils.Queue[*job]) m := &batchUuidsProviderMetrics{} var errors, err error + m.Requests, err = meter.Int64Counter( + "uuids.batch.request.sent", + metric.WithDescription("Number of UUIDs requests sent to Mojang API"), + metric.WithUnit("1"), + ) + errors = multierr.Append(errors, err) + + m.BatchSize, err = meter.Int64Histogram( + "uuids.batch.request.batch_size", + metric.WithDescription("The number of usernames in the query"), + metric.WithUnit("1"), + ) + errors = multierr.Append(errors, err) + m.QueueLength, err = meter.Int64ObservableGauge( - "queue.length", // TODO: look for better naming - metric.WithDescription(""), // TODO: description + "uuids.batch.queue.length", + metric.WithDescription("Number of tasks in the queue waiting for execution"), metric.WithInt64Callback(func(_ context.Context, o metric.Int64Observer) error { o.Observe(int64(queue.Len())) return nil @@ -176,23 +191,18 @@ func newBatchUuidsProviderMetrics(meter metric.Meter, queue *utils.Queue[*job]) errors = multierr.Append(errors, err) m.QueueTime, err = meter.Float64Histogram( - "queue.duration", - metric.WithDescription(""), // TODO: description + "uuids.batch.queue.lag", + metric.WithDescription("Lag between placing a job in the queue and starting its processing"), metric.WithUnit("ms"), ) - - m.BatchSize, err = meter.Int64Histogram( - "batch.size", - metric.WithDescription(""), // TODO: write description - metric.WithUnit("1"), - ) errors = multierr.Append(errors, err) return m, errors } type batchUuidsProviderMetrics struct { + Requests metric.Int64Counter + BatchSize metric.Int64Histogram QueueLength metric.Int64ObservableGauge QueueTime metric.Float64Histogram - BatchSize metric.Int64Histogram } diff --git a/internal/mojang/client.go b/internal/mojang/client.go index f9c7e4b..65cc28e 100644 --- a/internal/mojang/client.go +++ b/internal/mojang/client.go @@ -77,7 +77,6 @@ func (c *MojangApi) UsernamesToUuids(ctx context.Context, usernames []string) ([ // Obtains textures information for provided uuid // See https://wiki.vg/Mojang_API#UUID_-.3E_Profile_.2B_Skin.2FCape func (c *MojangApi) UuidToTextures(ctx context.Context, uuid string, signed bool) (*ProfileResponse, error) { - // TODO: normalize request url for tracing normalizedUuid := strings.ReplaceAll(uuid, "-", "") url := c.profileUrl + normalizedUuid if signed { diff --git a/internal/mojang/provider.go b/internal/mojang/provider.go index 68d4ac0..7945d78 100644 --- a/internal/mojang/provider.go +++ b/internal/mojang/provider.go @@ -59,7 +59,13 @@ func (p *MojangTexturesProvider) GetForUsername(ctx context.Context, username st username = strings.ToLower(username) result, err, shared := p.group.Do(username, func() (*ProfileResponse, error) { - profile, err := p.UuidsProvider.GetUuid(ctx, username) + var profile *ProfileInfo + var textures *ProfileResponse + var err error + + defer p.recordMetrics(ctx, profile, textures, err) + + profile, err = p.UuidsProvider.GetUuid(ctx, username) if err != nil { return nil, err } @@ -68,28 +74,36 @@ func (p *MojangTexturesProvider) GetForUsername(ctx context.Context, username st return nil, nil } - return p.TexturesProvider.GetTextures(ctx, profile.Id) - }) + textures, err = p.TexturesProvider.GetTextures(ctx, profile.Id) - p.recordMetrics(ctx, shared, result, err) - - return result, err -} + return textures, err + }) -func (p *MojangTexturesProvider) recordMetrics(ctx context.Context, shared bool, result *ProfileResponse, err error) { if shared { p.metrics.Shared.Add(ctx, 1) } + return result, err +} + +func (p *MojangTexturesProvider) recordMetrics(ctx context.Context, profile *ProfileInfo, textures *ProfileResponse, err error) { if err != nil { p.metrics.Failed.Add(ctx, 1) return } - if result != nil { - p.metrics.Found.Add(ctx, 1) + if profile == nil { + p.metrics.UsernameMissed.Add(ctx, 1) + p.metrics.TextureMissed.Add(ctx, 1) + + return + } + + p.metrics.UsernameFound.Add(ctx, 1) + if textures != nil { + p.metrics.TextureFound.Add(ctx, 1) } else { - p.metrics.Missed.Add(ctx, 1) + p.metrics.TextureMissed.Add(ctx, 1) } } @@ -104,27 +118,45 @@ func newProviderMetrics(meter metric.Meter) (*providerMetrics, error) { m := &providerMetrics{} var errors, err error - m.Found, err = meter.Int64Counter( - "results.found", - metric.WithDescription(""), // TODO: description + m.UsernameFound, err = meter.Int64Counter( + "provider.username_found", + metric.WithDescription("Number of queries for which username was found"), + metric.WithUnit("1"), + ) + errors = multierr.Append(errors, err) + + m.UsernameMissed, err = meter.Int64Counter( + "provider.username_missed", + metric.WithDescription("Number of queries for which username was not found"), + metric.WithUnit("1"), + ) + errors = multierr.Append(errors, err) + + m.TextureFound, err = meter.Int64Counter( + "provider.textures_found", + metric.WithDescription("Number of queries for which textures were successfully found"), + metric.WithUnit("1"), ) errors = multierr.Append(errors, err) - m.Missed, err = meter.Int64Counter( - "results.missed", - metric.WithDescription(""), // TODO: description + m.TextureMissed, err = meter.Int64Counter( + "provider.textures_missed", + metric.WithDescription("Number of queries for which no textures were found"), + metric.WithUnit("1"), ) errors = multierr.Append(errors, err) m.Failed, err = meter.Int64Counter( - "results.failed", - metric.WithDescription(""), // TODO: description + "provider.failed", + metric.WithDescription("Number of requests that ended in an error"), + metric.WithUnit("1"), ) errors = multierr.Append(errors, err) m.Shared, err = meter.Int64Counter( - "singleflight.shared", - metric.WithDescription(""), // TODO: description + "provider.singleflight.shared", + metric.WithDescription("Number of requests that are already being processed in another thread"), + metric.WithUnit("1"), ) errors = multierr.Append(errors, err) @@ -132,8 +164,10 @@ func newProviderMetrics(meter metric.Meter) (*providerMetrics, error) { } type providerMetrics struct { - Found metric.Int64Counter - Missed metric.Int64Counter - Failed metric.Int64Counter - Shared metric.Int64Counter + UsernameFound metric.Int64Counter + UsernameMissed metric.Int64Counter + TextureFound metric.Int64Counter + TextureMissed metric.Int64Counter + Failed metric.Int64Counter + Shared metric.Int64Counter } diff --git a/internal/mojang/textures_provider.go b/internal/mojang/textures_provider.go index 85c4d20..b21c004 100644 --- a/internal/mojang/textures_provider.go +++ b/internal/mojang/textures_provider.go @@ -100,8 +100,8 @@ func newMojangApiTexturesProviderMetrics(meter metric.Meter) (*mojangApiTextures var errors, err error m.Requests, err = meter.Int64Counter( - "textures.requests", - metric.WithDescription(""), // TODO: write description + "textures.request.sent", + metric.WithDescription("Number of textures requests sent to Mojang API"), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) @@ -119,14 +119,14 @@ func newTexturesProviderWithInMemoryCacheMetrics(meter metric.Meter) (*texturesP m.Hits, err = meter.Int64Counter( "textures.cache.hit", - metric.WithDescription(""), // TODO: write description + metric.WithDescription("Number of Mojang textures found in the local cache"), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) m.Misses, err = meter.Int64Counter( "textures.cache.miss", - metric.WithDescription(""), // TODO: write description + metric.WithDescription("Number of Mojang textures missing from local cache"), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) diff --git a/internal/mojang/uuids_provider.go b/internal/mojang/uuids_provider.go index 61ddfa2..48ab9fe 100644 --- a/internal/mojang/uuids_provider.go +++ b/internal/mojang/uuids_provider.go @@ -89,14 +89,14 @@ func newUuidsProviderWithCacheMetrics(meter metric.Meter) (*uuidsProviderWithCac m.Hits, err = meter.Int64Counter( "uuids.cache.hit", - metric.WithDescription(""), // TODO: write description + metric.WithDescription("Number of Mojang UUIDs found in the local cache"), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) m.Misses, err = meter.Int64Counter( "uuids.cache.miss", - metric.WithDescription(""), // TODO: write description + metric.WithDescription("Number of Mojang UUIDs missing from local cache"), metric.WithUnit("1"), ) errors = multierr.Append(errors, err) diff --git a/internal/otel/setup.go b/internal/otel/setup.go index 4c6b115..8058ac6 100644 --- a/internal/otel/setup.go +++ b/internal/otel/setup.go @@ -8,13 +8,11 @@ import ( "github.com/agoda-com/opentelemetry-go/otelslog" logsOtel "github.com/agoda-com/opentelemetry-logs-go" - "github.com/agoda-com/opentelemetry-logs-go/exporters/otlp/otlplogs" + logsAutoconfig "github.com/agoda-com/opentelemetry-logs-go/autoconfigure/sdk/logs" "github.com/agoda-com/opentelemetry-logs-go/sdk/logs" - logsSdk "github.com/agoda-com/opentelemetry-logs-go/sdk/logs" + "go.opentelemetry.io/contrib/exporters/autoexport" runtimeMetrics "go.opentelemetry.io/contrib/instrumentation/runtime" "go.opentelemetry.io/otel" - "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp" - "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/metric" "go.opentelemetry.io/otel/sdk/resource" @@ -122,43 +120,29 @@ func newResource(ctx context.Context) (*resource.Resource, error) { } func newLoggerProvider(ctx context.Context, res *resource.Resource) (*logs.LoggerProvider, error) { - exporter, err := otlplogs.NewExporter(ctx) - if err != nil { - return nil, err - } - - loggerProvider := logsSdk.NewLoggerProvider( - logsSdk.WithBatcher(exporter), - logsSdk.WithResource(res), - ) - - return loggerProvider, nil + return logsAutoconfig.NewLoggerProvider(ctx, logsAutoconfig.WithResource(res)), nil } func newTraceProvider(ctx context.Context, res *resource.Resource) (*trace.TracerProvider, error) { - traceExporter, err := otlptracehttp.New(ctx) + exporter, err := autoexport.NewSpanExporter(ctx) if err != nil { return nil, err } - traceProvider := trace.NewTracerProvider( + return trace.NewTracerProvider( + trace.WithBatcher(exporter), trace.WithResource(res), - trace.WithBatcher(traceExporter), - ) - - return traceProvider, nil + ), nil } func newMeterProvider(ctx context.Context, res *resource.Resource) (*metric.MeterProvider, error) { - metricExporter, err := otlpmetrichttp.New(ctx) + reader, err := autoexport.NewMetricReader(ctx) if err != nil { return nil, err } - meterProvider := metric.NewMeterProvider( + return metric.NewMeterProvider( + metric.WithReader(reader), metric.WithResource(res), - metric.WithReader(metric.NewPeriodicReader(metricExporter)), - ) - - return meterProvider, nil + ), nil }