telemetry: init telemetry package #80

closed
opened by anirudh.fi targeting master from tracing

Chill, it's not what you think. Helpers and middleware for tracing and metrics provided by OpenTelemetry.

Changed files
+326 -36
appview
cmd
appview
telemetry
+21 -6
go.mod
··· 26 github.com/sethvargo/go-envconfig v1.1.0 27 github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e 28 github.com/yuin/goldmark v1.4.13 29 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 30 ) 31 ··· 39 github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect 40 github.com/carlmjohnson/versioninfo v0.22.5 // indirect 41 github.com/casbin/govaluate v1.3.0 // indirect 42 github.com/cespare/xxhash/v2 v2.3.0 // indirect 43 github.com/cloudflare/circl v1.6.0 // indirect 44 github.com/davecgh/go-spew v1.1.1 // indirect ··· 47 github.com/felixge/httpsnoop v1.0.4 // indirect 48 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect 49 github.com/go-git/go-billy/v5 v5.6.2 // indirect 50 - github.com/go-logr/logr v1.4.1 // indirect 51 github.com/go-logr/stdr v1.2.2 // indirect 52 github.com/goccy/go-json v0.10.2 // indirect 53 github.com/gogo/protobuf v1.3.2 // indirect 54 github.com/gorilla/css v1.0.1 // indirect 55 github.com/gorilla/securecookie v1.1.2 // indirect 56 github.com/gorilla/websocket v1.5.1 // indirect 57 github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 58 github.com/hashicorp/go-retryablehttp v0.7.5 // indirect 59 github.com/hashicorp/golang-lru v1.0.2 // indirect ··· 99 github.com/xanzy/ssh-agent v0.3.3 // indirect 100 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect 101 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect 102 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect 103 - go.opentelemetry.io/otel v1.21.0 // indirect 104 - go.opentelemetry.io/otel/metric v1.21.0 // indirect 105 - go.opentelemetry.io/otel/trace v1.21.0 // indirect 106 go.uber.org/atomic v1.11.0 // indirect 107 go.uber.org/multierr v1.11.0 // indirect 108 go.uber.org/zap v1.26.0 // indirect 109 golang.org/x/crypto v0.37.0 // indirect 110 golang.org/x/net v0.39.0 // indirect 111 - golang.org/x/sys v0.32.0 // indirect 112 golang.org/x/time v0.5.0 // indirect 113 - google.golang.org/protobuf v1.34.2 // indirect 114 gopkg.in/warnings.v0 v0.1.2 // indirect 115 gopkg.in/yaml.v3 v3.0.1 // indirect 116 lukechampine.com/blake3 v1.2.1 // indirect
··· 26 github.com/sethvargo/go-envconfig v1.1.0 27 github.com/whyrusleeping/cbor-gen v0.2.1-0.20241030202151-b7a6831be65e 28 github.com/yuin/goldmark v1.4.13 29 + go.opentelemetry.io/otel v1.35.0 30 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 31 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 32 + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 33 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 34 + go.opentelemetry.io/otel/metric v1.35.0 35 + go.opentelemetry.io/otel/sdk v1.35.0 36 + go.opentelemetry.io/otel/sdk/metric v1.35.0 37 + go.opentelemetry.io/otel/trace v1.35.0 38 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 39 ) 40 ··· 48 github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect 49 github.com/carlmjohnson/versioninfo v0.22.5 // indirect 50 github.com/casbin/govaluate v1.3.0 // indirect 51 + github.com/cenkalti/backoff/v4 v4.3.0 // indirect 52 github.com/cespare/xxhash/v2 v2.3.0 // indirect 53 github.com/cloudflare/circl v1.6.0 // indirect 54 github.com/davecgh/go-spew v1.1.1 // indirect ··· 57 github.com/felixge/httpsnoop v1.0.4 // indirect 58 github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect 59 github.com/go-git/go-billy/v5 v5.6.2 // indirect 60 + github.com/go-logr/logr v1.4.2 // indirect 61 github.com/go-logr/stdr v1.2.2 // indirect 62 github.com/goccy/go-json v0.10.2 // indirect 63 github.com/gogo/protobuf v1.3.2 // indirect 64 github.com/gorilla/css v1.0.1 // indirect 65 github.com/gorilla/securecookie v1.1.2 // indirect 66 github.com/gorilla/websocket v1.5.1 // indirect 67 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect 68 github.com/hashicorp/go-cleanhttp v0.5.2 // indirect 69 github.com/hashicorp/go-retryablehttp v0.7.5 // indirect 70 github.com/hashicorp/golang-lru v1.0.2 // indirect ··· 110 github.com/xanzy/ssh-agent v0.3.3 // indirect 111 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect 112 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect 113 + go.opentelemetry.io/auto/sdk v1.1.0 // indirect 114 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect 115 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect 116 + go.opentelemetry.io/proto/otlp v1.5.0 // indirect 117 go.uber.org/atomic v1.11.0 // indirect 118 go.uber.org/multierr v1.11.0 // indirect 119 go.uber.org/zap v1.26.0 // indirect 120 golang.org/x/crypto v0.37.0 // indirect 121 golang.org/x/net v0.39.0 // indirect 122 + golang.org/x/sys v0.33.0 // indirect 123 + golang.org/x/text v0.24.0 // indirect 124 golang.org/x/time v0.5.0 // indirect 125 + google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a // indirect 126 + google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect 127 + google.golang.org/grpc v1.71.0 // indirect 128 + google.golang.org/protobuf v1.36.5 // indirect 129 gopkg.in/warnings.v0 v0.1.2 // indirect 130 gopkg.in/yaml.v3 v3.0.1 // indirect 131 lukechampine.com/blake3 v1.2.1 // indirect
+48 -18
go.sum
··· 42 github.com/casbin/govaluate v1.2.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= 43 github.com/casbin/govaluate v1.3.0 h1:VA0eSY0M2lA86dYd5kPPuNZMUD9QkWnOCnavGrw9myc= 44 github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= 45 github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 46 github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 47 github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= ··· 82 github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk= 83 github.com/go-git/go-git/v5 v5.6.1/go.mod h1:mvyoL6Unz0PiTQrGQfSfiLFhBH1c1e84ylC2MDs4ee8= 84 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 85 - github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= 86 - github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 87 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 88 github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 89 github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= ··· 93 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 94 github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= 95 github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 96 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 97 - github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 98 - github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 99 github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= 100 github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 101 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= ··· 111 github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= 112 github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= 113 github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= 114 github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 115 github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 116 github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= ··· 227 github.com/resend/resend-go/v2 v2.15.0 h1:B6oMEPf8IEQwn2Ovx/9yymkESLDSeNfLFaNMw+mzHhE= 228 github.com/resend/resend-go/v2 v2.15.0/go.mod h1:3YCb8c8+pLiqhtRFXTyFwlLvfjQtluxOr9HEh2BwCkQ= 229 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 230 - github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= 231 - github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= 232 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 233 github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= 234 github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= ··· 268 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8= 269 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q= 270 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I= 271 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= 272 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= 273 - go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= 274 - go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= 275 - go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= 276 - go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= 277 - go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= 278 - go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= 279 go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 280 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 281 go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= 282 go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= 283 go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= 284 - go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= 285 - go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= 286 go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= 287 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 288 go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= ··· 357 golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 358 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 359 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 360 - golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= 361 - golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 362 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 363 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 364 golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= ··· 395 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 396 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= 397 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= 398 - google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= 399 - google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= 400 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 401 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 402 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
··· 42 github.com/casbin/govaluate v1.2.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= 43 github.com/casbin/govaluate v1.3.0 h1:VA0eSY0M2lA86dYd5kPPuNZMUD9QkWnOCnavGrw9myc= 44 github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A= 45 + github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= 46 + github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= 47 github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 48 github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 49 github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= ··· 84 github.com/go-git/go-git/v5 v5.6.1 h1:q4ZRqQl4pR/ZJHc1L5CFjGA1a10u76aV1iC+nh+bHsk= 85 github.com/go-git/go-git/v5 v5.6.1/go.mod h1:mvyoL6Unz0PiTQrGQfSfiLFhBH1c1e84ylC2MDs4ee8= 86 github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 87 + github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 88 + github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 89 github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 90 github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 91 github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0= ··· 95 github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 96 github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= 97 github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 98 + github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 99 + github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 100 github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 101 + github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= 102 + github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 103 github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= 104 github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 105 github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= ··· 115 github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= 116 github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= 117 github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= 118 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 h1:e9Rjr40Z98/clHv5Yg79Is0NtosR5LXRvdr7o/6NwbA= 119 + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1/go.mod h1:tIxuGz/9mpox++sgp9fJjHO0+q1X9/UOWd798aAm22M= 120 github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= 121 github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= 122 github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= ··· 233 github.com/resend/resend-go/v2 v2.15.0 h1:B6oMEPf8IEQwn2Ovx/9yymkESLDSeNfLFaNMw+mzHhE= 234 github.com/resend/resend-go/v2 v2.15.0/go.mod h1:3YCb8c8+pLiqhtRFXTyFwlLvfjQtluxOr9HEh2BwCkQ= 235 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 236 + github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= 237 + github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= 238 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 239 github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= 240 github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= ··· 274 gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8= 275 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q= 276 gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I= 277 + go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= 278 + go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= 279 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= 280 go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= 281 + go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= 282 + go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= 283 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0 h1:QcFwRrZLc82r8wODjvyCbP7Ifp3UANaBSmhDSFjnqSc= 284 + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.35.0/go.mod h1:CXIWhUomyWBG/oY2/r/kLp6K/cmx9e/7DLpBuuGdLCA= 285 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= 286 + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= 287 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= 288 + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= 289 + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 h1:PB3Zrjs1sG1GBX51SXyTSoOTqcDglmsk7nT6tkKPb/k= 290 + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0/go.mod h1:U2R3XyVPzn0WX7wOIypPuptulsMcPDPs/oiSVOMVnHY= 291 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 h1:T0Ec2E+3YZf5bgTNQVet8iTDW7oIk03tXHq+wkwIDnE= 292 + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0/go.mod h1:30v2gqH+vYGJsesLWFov8u47EpYTcIQcBjKpI6pJThg= 293 + go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= 294 + go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= 295 + go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY= 296 + go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg= 297 + go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o= 298 + go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w= 299 + go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= 300 + go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= 301 + go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= 302 + go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= 303 go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 304 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 305 go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= 306 go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= 307 go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= 308 + go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= 309 + go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 310 go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= 311 go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 312 go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= ··· 381 golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 382 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 383 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 384 + golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= 385 + golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 386 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 387 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 388 golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= ··· 419 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 420 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= 421 golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= 422 + google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0= 423 + google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU= 424 + google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4= 425 + google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ= 426 + google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= 427 + google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= 428 + google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM= 429 + google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 430 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 431 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 432 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+88
telemetry/middleware.go
···
··· 1 + package telemetry 2 + 3 + import ( 4 + "fmt" 5 + "net/http" 6 + "time" 7 + 8 + "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" 9 + otelmetric "go.opentelemetry.io/otel/metric" 10 + "go.opentelemetry.io/otel/semconv/v1.13.0/httpconv" 11 + ) 12 + 13 + func (t *Telemetry) NewRequestDurationMillis() func(next http.Handler) http.Handler { 14 + const ( 15 + metricNameRequestDurationMs = "request_duration_millis" 16 + metricUnitRequestDurationMs = "ms" 17 + metricDescRequestDurationMs = "Measures the latency of HTTP requests processed by the server, in milliseconds." 18 + ) 19 + histogram, err := t.meter.Int64Histogram( 20 + metricNameRequestDurationMs, 21 + otelmetric.WithDescription(metricDescRequestDurationMs), 22 + otelmetric.WithUnit(metricUnitRequestDurationMs), 23 + ) 24 + if err != nil { 25 + panic(fmt.Sprintf("unable to create %s histogram: %v", metricNameRequestDurationMs, err)) 26 + } 27 + 28 + return func(next http.Handler) http.Handler { 29 + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 30 + // capture the start time of the request 31 + startTime := time.Now() 32 + 33 + // execute next http handler 34 + next.ServeHTTP(w, r) 35 + 36 + // record the request duration 37 + duration := time.Since(startTime) 38 + histogram.Record( 39 + r.Context(), 40 + int64(duration.Milliseconds()), 41 + otelmetric.WithAttributes( 42 + httpconv.ServerRequest(t.serviceName, r)..., 43 + ), 44 + ) 45 + }) 46 + } 47 + } 48 + 49 + func (t *Telemetry) NewRequestInFlight() func(next http.Handler) http.Handler { 50 + const ( 51 + metricNameRequestInFlight = "request_in_flight" 52 + metricDescRequestInFlight = "Measures the number of concurrent HTTP requests being processed by the server." 53 + metricUnitRequestInFlight = "1" 54 + ) 55 + 56 + // init metric, here we are using counter for capturing request in flight 57 + counter, err := t.meter.Int64UpDownCounter( 58 + metricNameRequestInFlight, 59 + otelmetric.WithDescription(metricDescRequestInFlight), 60 + otelmetric.WithUnit(metricUnitRequestInFlight), 61 + ) 62 + if err != nil { 63 + panic(fmt.Sprintf("unable to create %s counter: %v", metricNameRequestInFlight, err)) 64 + } 65 + 66 + return func(next http.Handler) http.Handler { 67 + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 68 + attrs := otelmetric.WithAttributes(httpconv.ServerRequest(t.serviceName, r)...) 69 + 70 + // increase the number of requests in flight 71 + counter.Add(r.Context(), 1, attrs) 72 + 73 + // execute next http handler 74 + next.ServeHTTP(w, r) 75 + 76 + // decrease the number of requests in flight 77 + counter.Add(r.Context(), -1, attrs) 78 + }) 79 + } 80 + } 81 + 82 + func (t *Telemetry) AddRoute() func(next http.Handler) http.Handler { 83 + return func(next http.Handler) http.Handler { 84 + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 85 + otelhttp.WithRouteTag(r.URL.Path, next) 86 + }) 87 + } 88 + }
+65
telemetry/provider.go
···
··· 1 + package telemetry 2 + 3 + import ( 4 + "context" 5 + "fmt" 6 + "time" 7 + 8 + "go.opentelemetry.io/otel" 9 + "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" 10 + "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" 11 + "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" 12 + "go.opentelemetry.io/otel/exporters/stdout/stdouttrace" 13 + "go.opentelemetry.io/otel/sdk/metric" 14 + "go.opentelemetry.io/otel/sdk/resource" 15 + "go.opentelemetry.io/otel/sdk/trace" 16 + ) 17 + 18 + func NewTracerProvider(ctx context.Context, res *resource.Resource, isDev bool) (*trace.TracerProvider, error) { 19 + var exporter trace.SpanExporter 20 + var err error 21 + 22 + if isDev { 23 + exporter, err = stdouttrace.New() 24 + if err != nil { 25 + return nil, fmt.Errorf("failed to create stdout trace exporter: %w", err) 26 + } 27 + } else { 28 + exporter, err = otlptracegrpc.New(ctx) 29 + if err != nil { 30 + return nil, fmt.Errorf("failed to create OTLP trace exporter: %w", err) 31 + } 32 + } 33 + 34 + tp := trace.NewTracerProvider( 35 + trace.WithBatcher(exporter), 36 + trace.WithResource(res), 37 + ) 38 + otel.SetTracerProvider(tp) 39 + 40 + return tp, nil 41 + } 42 + 43 + func NewMeterProvider(ctx context.Context, res *resource.Resource, isDev bool) (*metric.MeterProvider, error) { 44 + var exporter metric.Exporter 45 + var err error 46 + 47 + if isDev { 48 + exporter, err = stdoutmetric.New() 49 + if err != nil { 50 + return nil, fmt.Errorf("failed to create stdout metric exporter: %w", err) 51 + } 52 + } else { 53 + exporter, err = otlpmetricgrpc.New(ctx) 54 + if err != nil { 55 + return nil, fmt.Errorf("failed to create OTLP metric exporter: %w", err) 56 + } 57 + } 58 + 59 + mp := metric.NewMeterProvider( 60 + metric.WithReader(metric.NewPeriodicReader(exporter, metric.WithInterval(10*time.Second))), 61 + metric.WithResource(res), 62 + ) 63 + otel.SetMeterProvider(mp) 64 + return mp, nil 65 + }
+64
telemetry/telemetry.go
···
··· 1 + package telemetry 2 + 3 + import ( 4 + "context" 5 + 6 + otelmetric "go.opentelemetry.io/otel/metric" 7 + "go.opentelemetry.io/otel/sdk/metric" 8 + "go.opentelemetry.io/otel/sdk/resource" 9 + "go.opentelemetry.io/otel/sdk/trace" 10 + semconv "go.opentelemetry.io/otel/semconv/v1.17.0" 11 + oteltrace "go.opentelemetry.io/otel/trace" 12 + ) 13 + 14 + type Telemetry struct { 15 + tp *trace.TracerProvider 16 + mp *metric.MeterProvider 17 + 18 + meter otelmetric.Meter 19 + tracer oteltrace.Tracer 20 + 21 + serviceName string 22 + serviceVersion string 23 + } 24 + 25 + func NewTelemetry(ctx context.Context, serviceName, serviceVersion string, isDev bool) (*Telemetry, error) { 26 + res := resource.NewWithAttributes( 27 + semconv.SchemaURL, 28 + semconv.ServiceName(serviceName), 29 + semconv.ServiceVersion(serviceVersion), 30 + ) 31 + 32 + tp, err := NewTracerProvider(ctx, res, isDev) 33 + if err != nil { 34 + return nil, err 35 + } 36 + 37 + mp, err := NewMeterProvider(ctx, res, isDev) 38 + if err != nil { 39 + return nil, err 40 + } 41 + 42 + return &Telemetry{ 43 + tp: tp, 44 + mp: mp, 45 + 46 + meter: mp.Meter(serviceName), 47 + tracer: tp.Tracer(serviceVersion), 48 + 49 + serviceName: serviceName, 50 + serviceVersion: serviceVersion, 51 + }, nil 52 + } 53 + 54 + func (t *Telemetry) Meter() otelmetric.Meter { 55 + return t.meter 56 + } 57 + 58 + func (t *Telemetry) Tracer() oteltrace.Tracer { 59 + return t.tracer 60 + } 61 + 62 + func (t *Telemetry) TraceStart(ctx context.Context, name string) (context.Context, oteltrace.Span) { 63 + return ctx, oteltrace.SpanFromContext(ctx) 64 + }
+1
appview/config.go
··· 17 CamoSharedSecret string `env:"TANGLED_CAMO_SHARED_SECRET"` 18 AvatarSharedSecret string `env:"TANGLED_AVATAR_SHARED_SECRET"` 19 AvatarHost string `env:"TANGLED_AVATAR_HOST, default=https://avatar.tangled.sh"` 20 } 21 22 func LoadConfig(ctx context.Context) (*Config, error) {
··· 17 CamoSharedSecret string `env:"TANGLED_CAMO_SHARED_SECRET"` 18 AvatarSharedSecret string `env:"TANGLED_AVATAR_SHARED_SECRET"` 19 AvatarHost string `env:"TANGLED_AVATAR_HOST, default=https://avatar.tangled.sh"` 20 + EnableTelemetry bool `env:"TANGLED_TELEMETRY_ENABLED, default=false"` 21 } 22 23 func LoadConfig(ctx context.Context) (*Config, error) {
+6 -1
appview/state/router.go
··· 13 func (s *State) Router() http.Handler { 14 router := chi.NewRouter() 15 16 router.HandleFunc("/*", func(w http.ResponseWriter, r *http.Request) { 17 pat := chi.URLParam(r, "*") 18 if strings.HasPrefix(pat, "did:") || strings.HasPrefix(pat, "@") { ··· 48 49 func (s *State) UserRouter() http.Handler { 50 r := chi.NewRouter() 51 - 52 // strip @ from user 53 r.Use(StripLeadingAt) 54
··· 13 func (s *State) Router() http.Handler { 14 router := chi.NewRouter() 15 16 + if s.telemetry != nil { 17 + // top-level telemetry middleware 18 + router.Use(s.telemetry.NewRequestDurationMillis()) 19 + router.Use(s.telemetry.NewRequestInFlight()) 20 + } 21 + 22 router.HandleFunc("/*", func(w http.ResponseWriter, r *http.Request) { 23 pat := chi.URLParam(r, "*") 24 if strings.HasPrefix(pat, "did:") || strings.HasPrefix(pat, "@") { ··· 54 55 func (s *State) UserRouter() http.Handler { 56 r := chi.NewRouter() 57 // strip @ from user 58 r.Use(StripLeadingAt) 59
+29 -9
appview/state/state.go
··· 9 "log" 10 "log/slog" 11 "net/http" 12 "strings" 13 "time" 14 ··· 24 "tangled.sh/tangled.sh/core/appview/pages" 25 "tangled.sh/tangled.sh/core/jetstream" 26 "tangled.sh/tangled.sh/core/rbac" 27 ) 28 29 type State struct { 30 - db *db.DB 31 - auth *auth.Auth 32 - enforcer *rbac.Enforcer 33 - tidClock *syntax.TIDClock 34 - pages *pages.Pages 35 - resolver *appview.Resolver 36 - jc *jetstream.JetstreamClient 37 - config *appview.Config 38 } 39 40 - func Make(config *appview.Config) (*State, error) { 41 d, err := db.Make(config.DbPath) 42 if err != nil { 43 return nil, err ··· 59 60 resolver := appview.NewResolver() 61 62 wrapper := db.DbWrapper{d} 63 jc, err := jetstream.NewJetstreamClient( 64 config.JetstreamEndpoint, ··· 77 return nil, fmt.Errorf("failed to start jetstream watcher: %w", err) 78 } 79 80 state := &State{ 81 d, 82 auth, ··· 85 pgs, 86 resolver, 87 jc, 88 config, 89 } 90
··· 9 "log" 10 "log/slog" 11 "net/http" 12 + "runtime/debug" 13 "strings" 14 "time" 15 ··· 25 "tangled.sh/tangled.sh/core/appview/pages" 26 "tangled.sh/tangled.sh/core/jetstream" 27 "tangled.sh/tangled.sh/core/rbac" 28 + "tangled.sh/tangled.sh/core/telemetry" 29 ) 30 31 type State struct { 32 + db *db.DB 33 + auth *auth.Auth 34 + enforcer *rbac.Enforcer 35 + tidClock *syntax.TIDClock 36 + pages *pages.Pages 37 + resolver *appview.Resolver 38 + jc *jetstream.JetstreamClient 39 + telemetry *telemetry.Telemetry 40 + config *appview.Config 41 } 42 43 + func Make(ctx context.Context, config *appview.Config) (*State, error) { 44 d, err := db.Make(config.DbPath) 45 if err != nil { 46 return nil, err ··· 62 63 resolver := appview.NewResolver() 64 65 + bi, ok := debug.ReadBuildInfo() 66 + var version string 67 + if ok { 68 + version = bi.Main.Version 69 + } else { 70 + version = "v0.0.0-unknown" 71 + } 72 + 73 wrapper := db.DbWrapper{d} 74 jc, err := jetstream.NewJetstreamClient( 75 config.JetstreamEndpoint, ··· 88 return nil, fmt.Errorf("failed to start jetstream watcher: %w", err) 89 } 90 91 + var tele *telemetry.Telemetry 92 + if config.EnableTelemetry { 93 + tele, err = telemetry.NewTelemetry(ctx, "appview", version, config.Dev) 94 + if err != nil { 95 + return nil, fmt.Errorf("failed to setup telemetry: %w", err) 96 + } 97 + } 98 + 99 state := &State{ 100 d, 101 auth, ··· 104 pgs, 105 resolver, 106 jc, 107 + tele, 108 config, 109 } 110
+4 -2
cmd/appview/main.go
··· 14 func main() { 15 slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, nil))) 16 17 - c, err := appview.LoadConfig(context.Background()) 18 if err != nil { 19 log.Println("failed to load config", "error", err) 20 return 21 } 22 23 - state, err := state.Make(c) 24 25 if err != nil { 26 log.Fatal(err)
··· 14 func main() { 15 slog.SetDefault(slog.New(slog.NewTextHandler(os.Stdout, nil))) 16 17 + ctx := context.Background() 18 + 19 + c, err := appview.LoadConfig(ctx) 20 if err != nil { 21 log.Println("failed to load config", "error", err) 22 return 23 } 24 25 + state, err := state.Make(ctx, c) 26 27 if err != nil { 28 log.Fatal(err)