mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
feat(phase-bc): implement OTel SDK wiring and wazero plugin runtime
OTel (telemetry/telemetry_otel.go, -tags otel): - Real Init: prometheus pull-exporter + OTLP/gRPC push-exporter branches - Bridge types: Tracer/Span/Meter/Counter/Histogram/Gauge wrapping SDK - HTTP middleware via otelhttp (otelchi not in proxy; otelhttp is equivalent) - Added otel v1.43.0, sdk, exporters/prometheus v0.65.0, otlptracegrpc, otelhttp v0.67.0, wazero v1.11.0 to go.mod Wazero (plugin/sandbox_wazero.go, -tags wazero): - ensureRuntimeLocked: lazy wazero.Runtime init with WASI host module - activateWithRuntime: CompileModule + InstantiateModule per plugin - invokeCommand: JSON-ABI dispatch via allocate/command_dispatch/deallocate - listExportedCommands via list_commands export Build matrix: default, otel, wazero, postgres, otel+wazero+postgres all pass Server test suite: all packages green
This commit is contained in:
+14
-25
@@ -131,22 +131,15 @@ The session landed:
|
||||
|
||||
Still TODO locally:
|
||||
|
||||
- [ ] Add the OTel modules to `go.mod`:
|
||||
```sh
|
||||
cd Server
|
||||
go get go.opentelemetry.io/otel@latest \
|
||||
go.opentelemetry.io/otel/sdk@latest \
|
||||
go.opentelemetry.io/otel/exporters/prometheus@latest \
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc@latest \
|
||||
go.opentelemetry.io/contrib/instrumentation/github.com/go-chi/chi/v5/otelchi@latest
|
||||
go mod tidy
|
||||
```
|
||||
- [ ] Replace the placeholder body of `telemetry/telemetry_otel.go`'s
|
||||
`Init` with the real tracer + meter provider construction and the
|
||||
`otelchi.Middleware` wiring (see the inline TODO comment with the
|
||||
call graph).
|
||||
- [ ] Build with `-tags otel` once the SDK is in `go.mod` and add a CI
|
||||
job that exercises the tagged build.
|
||||
- [x] Add the OTel modules to `go.mod`:
|
||||
otel v1.43.0, sdk v1.43.0, exporters/prometheus v0.65.0,
|
||||
exporters/otlp/otlptrace/otlptracegrpc v1.43.0,
|
||||
otelhttp v0.67.0 (used instead of unavailable otelchi).
|
||||
- [x] Replace the placeholder body of `telemetry/telemetry_otel.go`'s
|
||||
`Init` with real SDK wiring: prometheus + otlp branches, bridge
|
||||
types for Tracer/Span/Meter/Counter/Histogram/Gauge, otelhttp
|
||||
middleware.
|
||||
- [x] Build with `-tags otel` — passes. Full 5-tag matrix green.
|
||||
- [x] Add spans to the remaining service-layer entry points
|
||||
(`DMService`, `VoiceService`, `InviteService`, `ModerationService`,
|
||||
`BlockService`, `UserService`) — landed in Pass 3, one entrypoint
|
||||
@@ -191,15 +184,11 @@ The session landed:
|
||||
|
||||
Still TODO locally:
|
||||
|
||||
- [ ] Add wazero to `go.mod`:
|
||||
```sh
|
||||
cd Server
|
||||
go get github.com/tetratelabs/wazero@latest
|
||||
go mod tidy
|
||||
```
|
||||
- [ ] Replace the placeholder body in `Server/plugin/sandbox_wazero.go`
|
||||
with real wazero runtime construction. The file contains an inline
|
||||
TODO with the exact API call graph.
|
||||
- [x] Add wazero to `go.mod`: v1.11.0 landed.
|
||||
- [x] Replace the placeholder body in `Server/plugin/sandbox_wazero.go`
|
||||
with real wazero runtime: lazy ensureRuntimeLocked, WASI host
|
||||
instantiation, CompileModule + InstantiateModule, JSON-ABI command
|
||||
dispatch, listExportedCommands via list_commands export.
|
||||
- [ ] Replace JSON-only manifest parsing with TOML support behind the
|
||||
`wazero` build tag (the design doc names `plugin.toml`). Add
|
||||
`github.com/BurntSushi/toml` and a `parseTOML` shim that falls back
|
||||
|
||||
+28
-17
@@ -4,8 +4,10 @@ go 1.25.0
|
||||
|
||||
require (
|
||||
aead.dev/minisign v0.3.0
|
||||
github.com/corazawaf/coraza/v3 v3.6.0
|
||||
github.com/go-chi/chi/v5 v5.2.5
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jackc/pgx/v5 v5.9.1
|
||||
github.com/knadh/koanf/parsers/yaml v1.1.0
|
||||
github.com/knadh/koanf/providers/env v1.1.0
|
||||
github.com/knadh/koanf/providers/file v1.2.1
|
||||
@@ -14,7 +16,17 @@ require (
|
||||
github.com/livekit/protocol v1.45.1
|
||||
github.com/livekit/server-sdk-go/v2 v2.16.0
|
||||
github.com/microcosm-cc/bluemonday v1.0.27
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
github.com/sasha-s/go-deadlock v0.3.9
|
||||
github.com/tetratelabs/wazero v1.11.0
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0
|
||||
go.opentelemetry.io/otel v1.43.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.65.0
|
||||
go.opentelemetry.io/otel/metric v1.43.0
|
||||
go.opentelemetry.io/otel/sdk v1.43.0
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0
|
||||
go.opentelemetry.io/otel/trace v1.43.0
|
||||
go.uber.org/goleak v1.3.0
|
||||
go.yaml.in/yaml/v3 v3.0.4
|
||||
golang.org/x/crypto v0.49.0
|
||||
@@ -28,19 +40,19 @@ require (
|
||||
buf.build/go/protovalidate v1.1.2 // indirect
|
||||
buf.build/go/protoyaml v0.6.0 // indirect
|
||||
cel.dev/expr v0.25.1 // indirect
|
||||
github.com/Shopify/toxiproxy/v2 v2.12.0 // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/benbjohnson/clock v1.3.5 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bep/debounce v1.2.1 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/corazawaf/coraza/v3 v3.6.0 // indirect
|
||||
github.com/corazawaf/libinjection-go v0.3.2 // indirect
|
||||
github.com/dennwc/iters v1.2.2 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/frostbyte73/core v0.1.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/gammazero/deque v1.2.1 // indirect
|
||||
@@ -52,23 +64,24 @@ require (
|
||||
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||
github.com/google/cel-go v0.27.0 // indirect
|
||||
github.com/gorilla/css v1.0.1 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 // indirect
|
||||
github.com/gotnospirit/makeplural v0.0.0-20180622080156-a5f48d94d976 // indirect
|
||||
github.com/gotnospirit/messageformat v0.0.0-20221001023931-dfe49f1eb092 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jxskiss/base62 v1.1.0 // indirect
|
||||
github.com/kaptinlin/go-i18n v0.1.4 // indirect
|
||||
github.com/kaptinlin/jsonschema v0.4.6 // indirect
|
||||
github.com/klauspost/compress v1.18.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||
github.com/knadh/koanf/maps v0.1.2 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/lithammer/shortuuid/v4 v4.2.0 // indirect
|
||||
github.com/livekit/mageutil v0.0.0-20250511045019-0f1ff63f7731 // indirect
|
||||
github.com/livekit/mediatransportutil v0.0.0-20251128105421-19c7a7b81c22 // indirect
|
||||
github.com/livekit/psrpc v0.7.1 // indirect
|
||||
github.com/magefile/mage v1.15.1-0.20250615140142-78acbaf2e3ae // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
@@ -96,16 +109,13 @@ require (
|
||||
github.com/pion/transport/v4 v4.0.1 // indirect
|
||||
github.com/pion/turn/v4 v4.1.4 // indirect
|
||||
github.com/pion/webrtc/v4 v4.2.9 // indirect
|
||||
github.com/prometheus/client_golang v1.22.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.64.0 // indirect
|
||||
github.com/prometheus/procfs v0.19.2 // indirect
|
||||
github.com/prometheus/common v0.67.5 // indirect
|
||||
github.com/prometheus/otlptranslator v1.0.0 // indirect
|
||||
github.com/prometheus/procfs v0.20.1 // indirect
|
||||
github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect
|
||||
github.com/redis/go-redis/v9 v9.17.2 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||
github.com/rs/xid v1.5.0 // indirect
|
||||
github.com/rs/zerolog v1.33.0 // indirect
|
||||
github.com/tidwall/gjson v1.18.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
@@ -113,23 +123,24 @@ require (
|
||||
github.com/valllabh/ocsf-schema-golang v1.0.3 // indirect
|
||||
github.com/wlynxg/anet v0.0.5 // indirect
|
||||
github.com/zeebo/xxh3 v1.1.0 // indirect
|
||||
go.opentelemetry.io/otel v1.40.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
go.uber.org/zap/exp v0.3.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.4 // indirect
|
||||
golang.org/x/exp v0.0.0-20260212183809-81e46e3db34a // indirect
|
||||
golang.org/x/net v0.52.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.42.0 // indirect
|
||||
golang.org/x/text v0.35.0 // indirect
|
||||
golang.org/x/time v0.14.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||
google.golang.org/grpc v1.79.3 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect
|
||||
google.golang.org/grpc v1.80.0 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
modernc.org/libc v1.70.0 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
|
||||
+67
-50
@@ -16,8 +16,6 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
|
||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
|
||||
github.com/Shopify/toxiproxy/v2 v2.12.0 h1:d1x++lYZg/zijXPPcv7PH0MvHMzEI5aX/YuUi/Sw+yg=
|
||||
github.com/Shopify/toxiproxy/v2 v2.12.0/go.mod h1:R9Z38Pw6k2cGZWXHe7tbxjGW9azmY1KbDQJ1kd+h7Tk=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
|
||||
github.com/antlr4-go/antlr/v4 v4.13.1/go.mod h1:GKmUxMtwp6ZgGwZSva4eWPC5mS6vUAmOABFgjdkM7Nw=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
@@ -36,6 +34,8 @@ github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/containerd/continuity v0.4.5 h1:ZRoN1sXq9u7V6QoHMcVWGhOwDFqZ4B9i5H6un1Wh0x4=
|
||||
@@ -44,12 +44,12 @@ github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG
|
||||
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||
github.com/corazawaf/coraza-coreruleset v0.0.0-20240226094324-415b1017abdc h1:OlJhrgI3I+FLUCTI3JJW8MoqyM78WbqJjecqMnqG+wc=
|
||||
github.com/corazawaf/coraza-coreruleset v0.0.0-20240226094324-415b1017abdc/go.mod h1:7rsocqNDkTCira5T0M7buoKR2ehh7YZiPkzxRuAgvVU=
|
||||
github.com/corazawaf/coraza/v3 v3.6.0 h1:rfsGl6eRBzzUAyADFcpuO7qXLt0DZtYWhfTIuhcyAjQ=
|
||||
github.com/corazawaf/coraza/v3 v3.6.0/go.mod h1:q7gszZCSufoHIy9jV2NCgk+glYwZpP2mIKgbu2dZkvE=
|
||||
github.com/corazawaf/libinjection-go v0.3.2 h1:9rrKt0lpg4WvUXt+lwS06GywfqRXXsa/7JcOw5cQLwI=
|
||||
github.com/corazawaf/libinjection-go v0.3.2/go.mod h1:Ik/+w3UmTWH9yn366RgS9D95K3y7Atb5m/H/gXzzPCk=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -71,6 +71,8 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/foxcpp/go-mockdns v1.1.0 h1:jI0rD8M0wuYAxL7r/ynTrCQQq0BVqfB99Vgk7DlmewI=
|
||||
github.com/foxcpp/go-mockdns v1.1.0/go.mod h1:IhLeSFGed3mJIAXPH2aiRQB+kqz7oqu8ld2qVbOu7Wk=
|
||||
github.com/frostbyte73/core v0.1.1 h1:ChhJOR7bAKOCPbA+lqDLE2cGKlCG5JXsDvvQr4YaJIA=
|
||||
github.com/frostbyte73/core v0.1.1/go.mod h1:mhfOtR+xWAvwXiwor7jnqPMnu4fxbv1F2MwZ0BEpzZo=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
@@ -92,7 +94,6 @@ github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/cel-go v0.27.0 h1:e7ih85+4qVrBuqQWTW4FKSqZYokVuc3HnhH5keboFTo=
|
||||
@@ -108,16 +109,26 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
||||
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5THxAzdVpqr6/geYxZytqFMBCOtn/ujyeo=
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/gotnospirit/makeplural v0.0.0-20180622080156-a5f48d94d976 h1:b70jEaX2iaJSPZULSUxKtm73LBfsCrMsIlYCUgNGSIs=
|
||||
github.com/gotnospirit/makeplural v0.0.0-20180622080156-a5f48d94d976/go.mod h1:ZGQeOwybjD8lkCjIyJfqR5LD2wMVHJ31d6GdPxoTsWY=
|
||||
github.com/gotnospirit/messageformat v0.0.0-20221001023931-dfe49f1eb092 h1:c7gcNWTSr1gtLp6PyYi3wzvFCEcHJ4YRobDgqmIgf7Q=
|
||||
github.com/gotnospirit/messageformat v0.0.0-20221001023931-dfe49f1eb092/go.mod h1:ZZAN4fkkful3l1lpJwF8JbW41ZiG9TwJ2ZlqzQovBNU=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 h1:HWRh5R2+9EifMyIHV7ZV+MIZqgz+PMpZ14Jynv3O2Zs=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0/go.mod h1:JfhWUomR1baixubs02l85lZYYOm7LV6om4ceouMv45c=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.9.1 h1:uwrxJXBnx76nyISkhr33kQLlUqjv7et7b9FjCen/tdc=
|
||||
github.com/jackc/pgx/v5 v5.9.1/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jcchavezs/mergefs v0.1.0 h1:7oteO7Ocl/fnfFMkoVLJxTveCjrsd//UB0j89xmnpec=
|
||||
github.com/jcchavezs/mergefs v0.1.0/go.mod h1:eRLTrsA+vFwQZ48hj8p8gki/5v9C2bFtHH5Mnn4bcGk=
|
||||
github.com/jxskiss/base62 v1.1.0 h1:A5zbF8v8WXx2xixnAKD2w+abC+sIzYJX+nxmhA6HWFw=
|
||||
github.com/jxskiss/base62 v1.1.0/go.mod h1:HhWAlUXvxKThfOlZbcuFzsqwtF5TcqS9ru3y5GfjWAc=
|
||||
github.com/kaptinlin/go-i18n v0.1.4 h1:wCiwAn1LOcvymvWIVAM4m5dUAMiHunTdEubLDk4hTGs=
|
||||
@@ -140,13 +151,12 @@ github.com/knadh/koanf/providers/structs v1.0.0 h1:DznjB7NQykhqCar2LvNug3MuxEQsZ
|
||||
github.com/knadh/koanf/providers/structs v1.0.0/go.mod h1:kjo5TFtgpaZORlpoJqcbeLowM2cINodv8kX+oFAeQ1w=
|
||||
github.com/knadh/koanf/v2 v2.3.3 h1:jLJC8XCRfLC7n4F+ZKKdBsbq1bfXTpuFhf4L7t94D94=
|
||||
github.com/knadh/koanf/v2 v2.3.3/go.mod h1:gRb40VRAbd4iJMYYD5IxZ6hfuopFcXBpc9bbQpZwo28=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/lithammer/shortuuid/v4 v4.2.0 h1:LMFOzVB3996a7b8aBuEXxqOBflbfPQAiVzkIcHO0h8c=
|
||||
github.com/lithammer/shortuuid/v4 v4.2.0/go.mod h1:D5noHZ2oFw/YaKCfGy0YxyE7M0wMbezmMjPdhyEFe6Y=
|
||||
github.com/livekit/mageutil v0.0.0-20250511045019-0f1ff63f7731 h1:9x+U2HGLrSw5ATTo469PQPkqzdoU7be46ryiCDO3boc=
|
||||
@@ -159,18 +169,14 @@ github.com/livekit/psrpc v0.7.1 h1:ms37az0QTD3UXIWuUC5D/SkmKOlRMVRsI261eBWu/Vw=
|
||||
github.com/livekit/psrpc v0.7.1/go.mod h1:bZ4iHFQptTkbPnB0LasvRNu/OBYXEu1NA6O5BMFo9kk=
|
||||
github.com/livekit/server-sdk-go/v2 v2.16.0 h1:xbr6PLprgasruzEk4Qv2sHVcK6r+cebUvaHxeE4UsZs=
|
||||
github.com/livekit/server-sdk-go/v2 v2.16.0/go.mod h1:+HCKTpzV21b/jvBtu+OmWbquUxaL74kHLI9ZwKmdhKU=
|
||||
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
|
||||
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
||||
github.com/magefile/mage v1.15.1-0.20250615140142-78acbaf2e3ae h1:yyMUG1VUd6IjV5jonMKpLXgwm9AzkfRsYisdCXc5OVI=
|
||||
github.com/magefile/mage v1.15.1-0.20250615140142-78acbaf2e3ae/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
|
||||
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
|
||||
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
|
||||
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
@@ -203,6 +209,8 @@ github.com/opencontainers/runc v1.3.3 h1:qlmBbbhu+yY0QM7jqfuat7M1H3/iXjju3VkP9lk
|
||||
github.com/opencontainers/runc v1.3.3/go.mod h1:D7rL72gfWxVs9cJ2/AayxB0Hlvn9g0gaF1R7uunumSI=
|
||||
github.com/ory/dockertest/v3 v3.12.0 h1:3oV9d0sDzlSQfHtIaB5k6ghUCVMVLpAY8hwrqoCyRCw=
|
||||
github.com/ory/dockertest/v3 v3.12.0/go.mod h1:aKNDTva3cp8dwOWwb9cWuX84aH5akkxXRvO7KCwWVjE=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/petar-dambovaliev/aho-corasick v0.0.0-20250424160509-463d218d4745 h1:Vpr4VgAizEgEZsaMohpw6JYDP+i9Of9dmdY4ufNP6HI=
|
||||
github.com/petar-dambovaliev/aho-corasick v0.0.0-20250424160509-463d218d4745/go.mod h1:EHPiTAKtiFmrMldLUNswFwfZ2eJIYBHktdaUTZxYWRw=
|
||||
github.com/petermattis/goid v0.0.0-20250813065127-a731cc31b4fe h1:vHpqOnPlnkba8iSxU4j/CvDSS9J4+F4473esQsYLGoE=
|
||||
@@ -241,20 +249,21 @@ github.com/pion/turn/v4 v4.1.4 h1:EU11yMXKIsK43FhcUnjLlrhE4nboHZq+TXBIi3QpcxQ=
|
||||
github.com/pion/turn/v4 v4.1.4/go.mod h1:ES1DXVFKnOhuDkqn9hn5VJlSWmZPaRJLyBXoOeO/BmQ=
|
||||
github.com/pion/webrtc/v4 v4.2.9 h1:DZIh1HAhPIL3RvwEDFsmL5hfPSLEpxsQk9/Jir2vkJE=
|
||||
github.com/pion/webrtc/v4 v4.2.9/go.mod h1:9EmLZve0H76eTzf8v2FmchZ6tcBXtDgpfTEu+drW6SY=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.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.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4=
|
||||
github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
|
||||
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
|
||||
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
|
||||
github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
|
||||
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
|
||||
github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos=
|
||||
github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM=
|
||||
github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc=
|
||||
github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||
github.com/redis/go-redis/v9 v9.17.2 h1:P2EGsA4qVIM3Pp+aPocCJ7DguDHhqrXNhVcEp4ViluI=
|
||||
@@ -263,13 +272,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rodaine/protogofakeit v0.1.1 h1:ZKouljuRM3A+TArppfBqnH8tGZHOwM/pjvtXe9DaXH8=
|
||||
github.com/rodaine/protogofakeit v0.1.1/go.mod h1:pXn/AstBYMaSfc1/RqH3N82pBuxtWgejz1AlYpY1mI0=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||
github.com/sasha-s/go-deadlock v0.3.9 h1:fiaT9rB7g5sr5ddNZvlwheclN9IP86eFW9WgqlEQV+w=
|
||||
github.com/sasha-s/go-deadlock v0.3.9/go.mod h1:KuZj51ZFmx42q/mPaYbRk0P1xcwe697zsJKE03vD4/Y=
|
||||
github.com/shoenig/test v1.7.0 h1:eWcHtTXa6QLnBvm0jgEabMRN/uJ4DMV3M8xUGgRkZmk=
|
||||
@@ -277,9 +281,12 @@ github.com/shoenig/test v1.7.0/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsB
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tetratelabs/wazero v1.11.0 h1:+gKemEuKCTevU4d7ZTzlsvgd1uaToIDtlQlmNbwqYhA=
|
||||
github.com/tetratelabs/wazero v1.11.0/go.mod h1:eV28rsN8Q+xwjogd7f4/Pp4xFxO7uOGbLcD/LzB1wiU=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
@@ -306,14 +313,26 @@ github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs=
|
||||
github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
|
||||
go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
|
||||
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
|
||||
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
|
||||
go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
|
||||
go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=
|
||||
go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 h1:OyrsyzuttWTSur2qN/Lm0m2a8yqyIjUVBZcxFPuXq2o=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0/go.mod h1:C2NGBr+kAB4bk3xtMXfZ94gqFDtg/GkI7e9zqGh5Beg=
|
||||
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
|
||||
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0 h1:88Y4s2C8oTui1LGM6bTWkw0ICGcOLCAI5l6zsD1j20k=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.43.0/go.mod h1:Vl1/iaggsuRlrHf/hfPJPvVag77kKyvrLeD10kpMl+A=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0 h1:RAE+JPfvEmvy+0LzyUA25/SGawPwIUbZ6u0Wug54sLc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.43.0/go.mod h1:AGmbycVGEsRx9mXMZ75CsOyhSP6MFIcj/6dnG+vhVjk=
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.65.0 h1:jOveH/b4lU9HT7y+Gfamf18BqlOuz2PWEvs8yM7Q6XE=
|
||||
go.opentelemetry.io/otel/exporters/prometheus v0.65.0/go.mod h1:i1P8pcumauPtUI4YNopea1dhzEMuEqWP1xoUZDylLHo=
|
||||
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
|
||||
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0 h1:S88dyqXjJkuBNLeMcVPRFXpRw2fuwdvfCGLEo89fDkw=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.43.0/go.mod h1:C/RJtwSEJ5hzTiUz5pXF1kILHStzb9zFlIEe85bhj6A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
|
||||
go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g=
|
||||
go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
@@ -324,6 +343,8 @@ go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
go.uber.org/zap/exp v0.3.0 h1:6JYzdifzYkGmTdRR59oYH+Ng7k49H9qVpWwNSsGJj3U=
|
||||
go.uber.org/zap/exp v0.3.0/go.mod h1:5I384qq7XGxYyByIhHm6jg5CHkGY0nsTfbDLgDDlgJQ=
|
||||
go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
|
||||
go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
@@ -342,8 +363,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -356,11 +375,9 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
@@ -386,19 +403,19 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
|
||||
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 h1:JLQynH/LBHfCTSbDWl+py8C+Rg/k1OVH3xfcaiANuF0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:kSJwQxqmFXeo79zOmbrALdflXQeAYcUbgS7PbpMknCY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 h1:mWPCjDEyshlQYzBpMNHaEof6UX1PmHcaUODUywQ0uac=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||
google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
|
||||
google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
|
||||
gonum.org/v1/gonum v0.17.0 h1:VbpOemQlsSMrYmn7T2OUvQ4dqxQXU+ouZFQsZOx50z4=
|
||||
gonum.org/v1/gonum v0.17.0/go.mod h1:El3tOrEuMpv2UdMrbNlKEh9vd86bmQ6vqIcDwxEOc1E=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9 h1:VPWxll4HlMw1Vs/qXtN7BvhZqsS9cdAittCNvVENElA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:7QBABkRtR8z+TEnmXTqIqwJLlzrZKVfAUm7tY3yGv0M=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 h1:m8qni9SQFH0tJc1X0vmnpw/0t+AImlSvp30sEupozUg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||
google.golang.org/grpc v1.80.0 h1:Xr6m2WmWZLETvUNvIUmeD5OAagMw3FiKmMlTdViWsHM=
|
||||
google.golang.org/grpc v1.80.0/go.mod h1:ho/dLnxwi3EDJA4Zghp7k2Ec1+c2jqup0bFkw07bwF4=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -380,9 +380,6 @@ func (r *Registry) activateAll(ctx context.Context) error {
|
||||
// ErrRuntimeUnavailable; the wazero-tagged build replaces this with the real
|
||||
// implementation via the runtimePlatform field.
|
||||
func (r *Registry) activate(ctx context.Context, inst *Instance) error {
|
||||
if r.runtimePlatform == nil {
|
||||
return ErrRuntimeUnavailable
|
||||
}
|
||||
return r.activateWithRuntime(ctx, inst)
|
||||
}
|
||||
|
||||
|
||||
+191
-58
@@ -1,79 +1,212 @@
|
||||
//go:build wazero
|
||||
|
||||
// Real Wazero-backed plugin runtime. Compiled only with `-tags wazero`,
|
||||
// matching the postgres / otel build-tag pattern used elsewhere in the repo.
|
||||
//
|
||||
// IMPORTANT: This file is a structural skeleton — it will fail to compile
|
||||
// until github.com/tetratelabs/wazero is added to go.mod. To finish wiring it
|
||||
// on a machine with network access:
|
||||
//
|
||||
// cd Server
|
||||
// go get github.com/tetratelabs/wazero@latest
|
||||
// go mod tidy
|
||||
// go build -tags wazero ./...
|
||||
//
|
||||
// The skeleton documents the intended call graph so the implementation work
|
||||
// is mechanical: each TODO marker maps to a wazero API call.
|
||||
// Real Wazero-backed plugin runtime. Compiled only with `-tags wazero`.
|
||||
// Provides concrete implementations of activateWithRuntime and invokeCommand
|
||||
// that compile, instantiate, and dispatch to WASM modules via wazero v1.
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/tetratelabs/wazero"
|
||||
"github.com/tetratelabs/wazero/api"
|
||||
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"
|
||||
)
|
||||
|
||||
// activateWithRuntime compiles inst.WASMPath into a wazero module, applies
|
||||
// the per-plugin resource caps, and registers exported functions for each
|
||||
// declared capability.
|
||||
// wazeroPageBytes is the size of a single WASM linear-memory page (64 KiB).
|
||||
const wazeroPageBytes = 65536
|
||||
|
||||
// ensureRuntimeLocked initialises the shared wazero.Runtime on first call.
|
||||
// The caller MUST hold r.mu.Lock().
|
||||
func (r *Registry) ensureRuntimeLocked(ctx context.Context) (wazero.Runtime, error) {
|
||||
if r.runtimePlatform != nil {
|
||||
rt, ok := r.runtimePlatform.(wazero.Runtime)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("plugin: runtimePlatform is not a wazero.Runtime")
|
||||
}
|
||||
return rt, nil
|
||||
}
|
||||
|
||||
// Convert the configured MB limit to WASM pages (64 KiB each).
|
||||
memMB := r.cfg.MaxMemoryMB
|
||||
if memMB <= 0 {
|
||||
memMB = 64 // default 64 MiB
|
||||
}
|
||||
memPages := uint32(memMB) * 1024 * 1024 / wazeroPageBytes
|
||||
|
||||
rtCfg := wazero.NewRuntimeConfig().WithMemoryLimitPages(memPages)
|
||||
rt := wazero.NewRuntimeWithConfig(ctx, rtCfg)
|
||||
|
||||
// Instantiate the WASI host module so plugins compiled with the WASI
|
||||
// target (TinyGo, wasm32-wasi, etc.) have their syscall shims available.
|
||||
if _, err := wasi_snapshot_preview1.Instantiate(ctx, rt); err != nil {
|
||||
_ = rt.Close(ctx)
|
||||
return nil, fmt.Errorf("plugin: wasi instantiation: %w", err)
|
||||
}
|
||||
|
||||
r.runtimePlatform = rt
|
||||
return rt, nil
|
||||
}
|
||||
|
||||
// activateWithRuntime compiles inst.WASMPath into a wazero module, instantiates
|
||||
// it, and wires up the command dispatch table for any commands the module exports.
|
||||
func (r *Registry) activateWithRuntime(ctx context.Context, inst *Instance) error {
|
||||
wasmBytes, err := os.ReadFile(inst.WASMPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("plugin %q: read wasm: %w", inst.Manifest.Name, err)
|
||||
}
|
||||
_ = wasmBytes
|
||||
_ = ctx
|
||||
|
||||
// TODO(wazero): replace with the real wiring once go.mod has wazero:
|
||||
//
|
||||
// runtime := r.runtimePlatform.(wazero.Runtime)
|
||||
// compiled, err := runtime.CompileModule(ctx, wasmBytes)
|
||||
// if err != nil { return fmt.Errorf("compile: %w", err) }
|
||||
//
|
||||
// modCfg := wazero.NewModuleConfig().
|
||||
// WithName(inst.Manifest.Name).
|
||||
// WithStdout(io.Discard).
|
||||
// WithStderr(io.Discard)
|
||||
//
|
||||
// memBytes := uint32(inst.Manifest.Resources.MaxMemoryMB)
|
||||
// if memBytes == 0 { memBytes = uint32(r.cfg.MaxMemoryMB) }
|
||||
// // wazero pages are 64 KiB; the runtime config caps via WithMemoryLimitPages.
|
||||
//
|
||||
// module, err := runtime.InstantiateModule(ctx, compiled, modCfg)
|
||||
// if err != nil { return fmt.Errorf("instantiate: %w", err) }
|
||||
//
|
||||
// inst.module = module
|
||||
//
|
||||
// // Walk inst.Manifest.Permissions and call host_*.Register* for each
|
||||
// // capability so the runtime knows what exports to look for.
|
||||
// Ensure the shared runtime is ready (lazy init, holds lock only briefly).
|
||||
r.mu.Lock()
|
||||
rt, err := r.ensureRuntimeLocked(ctx)
|
||||
r.mu.Unlock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return fmt.Errorf("plugin %q: wazero runtime skeleton incomplete (see sandbox_wazero.go)", inst.Manifest.Name)
|
||||
// CompileModule is CPU-intensive but requires no lock.
|
||||
compiled, err := rt.CompileModule(ctx, wasmBytes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("plugin %q: compile: %w", inst.Manifest.Name, err)
|
||||
}
|
||||
|
||||
modCfg := wazero.NewModuleConfig().
|
||||
WithName(inst.Manifest.Name).
|
||||
WithStdout(io.Discard).
|
||||
WithStderr(io.Discard).
|
||||
WithStartFunctions() // suppress _start; exports are called on demand
|
||||
|
||||
module, err := rt.InstantiateModule(ctx, compiled, modCfg)
|
||||
if err != nil {
|
||||
_ = compiled.Close(ctx)
|
||||
return fmt.Errorf("plugin %q: instantiate: %w", inst.Manifest.Name, err)
|
||||
}
|
||||
|
||||
// Register the module and bind any commands it exports.
|
||||
r.mu.Lock()
|
||||
inst.module = module
|
||||
for _, perm := range inst.Manifest.Permissions {
|
||||
if Capability(perm) == CapCommands {
|
||||
for _, cmd := range listExportedCommands(ctx, module) {
|
||||
r.commands[cmd] = inst
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
r.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
// invokeCommand calls the plugin's `command_dispatch` exported function with
|
||||
// the marshalled command + args, and decodes the response into a CommandResult.
|
||||
// invokeCommand calls the plugin's exported "command_dispatch" function using
|
||||
// a simple linear-memory ABI:
|
||||
//
|
||||
// allocate(size u32) → ptr u32
|
||||
// command_dispatch(ptr u32, len u32) → (result_ptr u32, result_len u32)
|
||||
// deallocate(ptr u32, len u32)
|
||||
//
|
||||
// Both the input and output are JSON payloads.
|
||||
func (r *Registry) invokeCommand(ctx context.Context, inst *Instance, userID, channelID int64, cmd string, args []string) (*CommandResult, bool) {
|
||||
_ = ctx
|
||||
_ = inst
|
||||
_ = userID
|
||||
_ = channelID
|
||||
_ = cmd
|
||||
_ = args
|
||||
// TODO(wazero): real call:
|
||||
// fn := module.ExportedFunction("command_dispatch")
|
||||
// payload := encodeCommand(userID, channelID, cmd, args)
|
||||
// result, err := fn.Call(ctx, ...)
|
||||
// ...
|
||||
return &CommandResult{
|
||||
Reply: "plugin runtime: command dispatch not yet implemented in skeleton",
|
||||
}, true
|
||||
if inst.module == nil {
|
||||
return nil, false
|
||||
}
|
||||
mod, ok := inst.module.(api.Module)
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
dispatchFn := mod.ExportedFunction("command_dispatch")
|
||||
if dispatchFn == nil {
|
||||
return nil, false
|
||||
}
|
||||
allocFn := mod.ExportedFunction("allocate")
|
||||
deallocFn := mod.ExportedFunction("deallocate")
|
||||
if allocFn == nil {
|
||||
return &CommandResult{
|
||||
Reply: fmt.Sprintf("plugin %s: missing allocate export (required for command dispatch)", inst.Manifest.Name),
|
||||
}, true
|
||||
}
|
||||
|
||||
type dispatchPayload struct {
|
||||
UserID int64 `json:"user_id"`
|
||||
ChannelID int64 `json:"channel_id"`
|
||||
Command string `json:"command"`
|
||||
Args []string `json:"args"`
|
||||
}
|
||||
payload, err := json.Marshal(dispatchPayload{
|
||||
UserID: userID, ChannelID: channelID, Command: cmd, Args: args,
|
||||
})
|
||||
if err != nil {
|
||||
return &CommandResult{Reply: fmt.Sprintf("plugin %s: marshal payload: %v", inst.Manifest.Name, err)}, true
|
||||
}
|
||||
|
||||
// Allocate guest memory for the input payload.
|
||||
size := uint64(len(payload))
|
||||
ptrs, callErr := allocFn.Call(ctx, size)
|
||||
if callErr != nil || len(ptrs) == 0 {
|
||||
return &CommandResult{Reply: fmt.Sprintf("plugin %s: allocate(%d): %v", inst.Manifest.Name, size, callErr)}, true
|
||||
}
|
||||
ptr := ptrs[0]
|
||||
|
||||
mem := mod.Memory()
|
||||
if !mem.Write(uint32(ptr), payload) {
|
||||
return &CommandResult{Reply: fmt.Sprintf("plugin %s: memory write at %d failed", inst.Manifest.Name, ptr)}, true
|
||||
}
|
||||
|
||||
results, callErr := dispatchFn.Call(ctx, ptr, size)
|
||||
|
||||
// Free the input buffer regardless of dispatch outcome.
|
||||
if deallocFn != nil {
|
||||
_, _ = deallocFn.Call(ctx, ptr, size)
|
||||
}
|
||||
|
||||
if callErr != nil {
|
||||
return &CommandResult{Reply: fmt.Sprintf("plugin %s: dispatch: %v", inst.Manifest.Name, callErr)}, true
|
||||
}
|
||||
if len(results) < 2 {
|
||||
return &CommandResult{Reply: fmt.Sprintf("plugin %s: command_dispatch returned %d values, want 2", inst.Manifest.Name, len(results))}, true
|
||||
}
|
||||
|
||||
resPtr, resLen := uint32(results[0]), uint32(results[1])
|
||||
resBytes, ok2 := mem.Read(resPtr, resLen)
|
||||
if !ok2 {
|
||||
return &CommandResult{Reply: fmt.Sprintf("plugin %s: cannot read result at %d+%d", inst.Manifest.Name, resPtr, resLen)}, true
|
||||
}
|
||||
|
||||
type dispatchResult struct {
|
||||
Reply string `json:"reply"`
|
||||
}
|
||||
var dr dispatchResult
|
||||
if err := json.Unmarshal(resBytes, &dr); err != nil {
|
||||
// Fall back to raw bytes if the JSON is malformed.
|
||||
return &CommandResult{Reply: string(resBytes)}, true
|
||||
}
|
||||
return &CommandResult{Reply: dr.Reply}, true
|
||||
}
|
||||
|
||||
// listExportedCommands calls the plugin's optional "list_commands" export which
|
||||
// returns (ptr u32, len u32) pointing to a JSON array of command name strings.
|
||||
// If the export is absent or returns invalid JSON, an empty slice is returned.
|
||||
func listExportedCommands(ctx context.Context, mod api.Module) []string {
|
||||
fn := mod.ExportedFunction("list_commands")
|
||||
if fn == nil {
|
||||
return nil
|
||||
}
|
||||
results, err := fn.Call(ctx)
|
||||
if err != nil || len(results) < 2 {
|
||||
return nil
|
||||
}
|
||||
ptr, length := uint32(results[0]), uint32(results[1])
|
||||
raw, ok := mod.Memory().Read(ptr, length)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
var cmds []string
|
||||
if err := json.Unmarshal(raw, &cmds); err != nil {
|
||||
return nil
|
||||
}
|
||||
return cmds
|
||||
}
|
||||
|
||||
@@ -1,26 +1,8 @@
|
||||
//go:build otel
|
||||
|
||||
// Real OpenTelemetry-backed implementation. Compiled only with `-tags otel`,
|
||||
// which keeps the OTel SDK out of the default sqlite-only build (matching the
|
||||
// pattern used by Server/store/postgres.go).
|
||||
//
|
||||
// IMPORTANT: This file currently compiles under `-tags otel` because the
|
||||
// skeleton deliberately avoids importing any upstream OTel packages. `Init`
|
||||
// returns a runtime error until the real SDK wiring lands; `Shutdown` is a
|
||||
// no-op. The CI matrix step that builds with `-tags otel` therefore passes
|
||||
// today but does NOT exercise real telemetry. To finish wiring it, run on
|
||||
// a machine with network access:
|
||||
//
|
||||
// cd Server
|
||||
// go get go.opentelemetry.io/otel@latest \
|
||||
// go.opentelemetry.io/otel/sdk@latest \
|
||||
// go.opentelemetry.io/otel/exporters/prometheus@latest \
|
||||
// go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc@latest \
|
||||
// go.opentelemetry.io/contrib/instrumentation/github.com/go-chi/chi/v5/otelchi@latest
|
||||
// go mod tidy
|
||||
// go build -tags otel ./...
|
||||
//
|
||||
// Until that runs, the default build (no `-tags otel`) uses telemetry_default.go.
|
||||
// Real OpenTelemetry-backed implementation. Compiled only with `-tags otel`.
|
||||
// Replaces the no-op providers in telemetry_default.go for the duration of
|
||||
// the process.
|
||||
package telemetry
|
||||
|
||||
import (
|
||||
@@ -28,51 +10,227 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
otlpgrpc "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
|
||||
promexp "go.opentelemetry.io/otel/exporters/prometheus"
|
||||
otelmetric "go.opentelemetry.io/otel/metric"
|
||||
sdkmetric "go.opentelemetry.io/otel/sdk/metric"
|
||||
sdkresource "go.opentelemetry.io/otel/sdk/resource"
|
||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||
oteltrace "go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/owncord/server/config"
|
||||
)
|
||||
|
||||
// otelProvider is the placeholder for the real OTel-backed Provider. The
|
||||
// fields and methods will be filled in once the OTel modules are in go.mod;
|
||||
// for now this file exists so reviewers can see the intended shape and the
|
||||
// `otel` build tag has a target.
|
||||
// otelProvider is the real OTel-backed Provider, active only in the otel build.
|
||||
type otelProvider struct {
|
||||
cfg config.TelemetryConfig
|
||||
promHandler http.Handler
|
||||
httpMiddleware func(http.Handler) http.Handler
|
||||
shutdown ShutdownFunc
|
||||
tp oteltrace.TracerProvider
|
||||
mp otelmetric.MeterProvider
|
||||
promHandler http.Handler
|
||||
mw func(http.Handler) http.Handler
|
||||
shutdowns []func(context.Context) error
|
||||
}
|
||||
|
||||
// Init wires the OTel SDK exporters according to cfg.Exporter:
|
||||
//
|
||||
// "none" — no-op (matches the default build)
|
||||
// "prometheus" — pull-based Prometheus exporter mounted at /metrics
|
||||
// "otlp" — push-based OTLP/gRPC exporter to cfg.OTLPEndpoint
|
||||
//
|
||||
// All exporters share the same resource (service.name = cfg.ServiceName).
|
||||
// Init wires the OTel SDK according to cfg.Exporter and installs the result
|
||||
// as the global telemetry provider. The returned ShutdownFunc must be called
|
||||
// on server shutdown to flush pending telemetry.
|
||||
func Init(ctx context.Context, cfg config.TelemetryConfig) (ShutdownFunc, error) {
|
||||
if !cfg.Enabled || cfg.Exporter == "" || cfg.Exporter == "none" {
|
||||
SetGlobal(noopProvider{})
|
||||
return func(context.Context) error { return nil }, nil
|
||||
}
|
||||
|
||||
// TODO(otel-build-tag): replace the panic below with the real OTel
|
||||
// initialisation once go.mod has the otel modules. The structural call
|
||||
// graph is:
|
||||
//
|
||||
// resource = sdkresource.NewWithAttributes(...)
|
||||
// tp = sdktrace.NewTracerProvider(WithBatcher(otlptracegrpc...))
|
||||
// mp = sdkmetric.NewMeterProvider(WithReader(prometheus.New()))
|
||||
// otel.SetTracerProvider(tp); otel.SetMeterProvider(mp)
|
||||
// handler = promhttp.HandlerFor(prometheusReg, promhttp.HandlerOpts{})
|
||||
// mw = otelchi.Middleware(serviceName, otelchi.WithChiRoutes(...))
|
||||
//
|
||||
// then wrap them in a Provider implementation and SetGlobal it.
|
||||
_ = ctx
|
||||
return nil, fmt.Errorf("telemetry: otel build tag is set but the SDK skeleton in telemetry_otel.go is incomplete; finish wiring after `go get go.opentelemetry.io/otel...`")
|
||||
res, err := sdkresource.New(ctx,
|
||||
sdkresource.WithAttributes(attribute.String("service.name", cfg.ServiceName)),
|
||||
sdkresource.WithFromEnv(),
|
||||
)
|
||||
if err != nil {
|
||||
// Non-fatal: fall back to the SDK default resource.
|
||||
res = sdkresource.Default()
|
||||
}
|
||||
|
||||
p := &otelProvider{}
|
||||
|
||||
switch cfg.Exporter {
|
||||
case "prometheus":
|
||||
promReg := prometheus.NewRegistry()
|
||||
exporter, expErr := promexp.New(promexp.WithRegisterer(promReg))
|
||||
if expErr != nil {
|
||||
return nil, fmt.Errorf("telemetry: prometheus exporter: %w", expErr)
|
||||
}
|
||||
mp := sdkmetric.NewMeterProvider(
|
||||
sdkmetric.WithResource(res),
|
||||
sdkmetric.WithReader(exporter),
|
||||
)
|
||||
otel.SetMeterProvider(mp)
|
||||
p.mp = mp
|
||||
p.promHandler = promhttp.HandlerFor(promReg, promhttp.HandlerOpts{EnableOpenMetrics: true})
|
||||
p.shutdowns = append(p.shutdowns, mp.Shutdown)
|
||||
|
||||
case "otlp":
|
||||
if cfg.OTLPEndpoint == "" {
|
||||
return nil, fmt.Errorf("telemetry: exporter=otlp requires otlp_endpoint to be set")
|
||||
}
|
||||
exp, expErr := otlpgrpc.New(ctx,
|
||||
otlpgrpc.WithEndpoint(cfg.OTLPEndpoint),
|
||||
otlpgrpc.WithInsecure(),
|
||||
)
|
||||
if expErr != nil {
|
||||
return nil, fmt.Errorf("telemetry: otlp exporter: %w", expErr)
|
||||
}
|
||||
tp := sdktrace.NewTracerProvider(
|
||||
sdktrace.WithBatcher(exp),
|
||||
sdktrace.WithResource(res),
|
||||
)
|
||||
otel.SetTracerProvider(tp)
|
||||
p.tp = tp
|
||||
p.shutdowns = append(p.shutdowns, tp.Shutdown)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("telemetry: unknown exporter %q (valid: none, prometheus, otlp)", cfg.Exporter)
|
||||
}
|
||||
|
||||
// HTTP tracing middleware using otelhttp (works with any http.Handler router).
|
||||
p.mw = func(next http.Handler) http.Handler {
|
||||
return otelhttp.NewHandler(next, cfg.ServiceName)
|
||||
}
|
||||
|
||||
SetGlobal(p)
|
||||
return p.shutdown, nil
|
||||
}
|
||||
|
||||
// otelProvider satisfies Provider once the SDK is wired.
|
||||
func (p *otelProvider) Tracer(name string) Tracer { _ = name; return noopTracer{} }
|
||||
func (p *otelProvider) Meter(name string) Meter { _ = name; return noopMeter{} }
|
||||
func (p *otelProvider) HTTPMiddleware(next http.Handler) http.Handler { return p.httpMiddleware(next) }
|
||||
func (p *otelProvider) PrometheusHandler() http.Handler { return p.promHandler }
|
||||
func (p *otelProvider) shutdown(ctx context.Context) error {
|
||||
var first error
|
||||
for _, fn := range p.shutdowns {
|
||||
if err := fn(ctx); err != nil && first == nil {
|
||||
first = err
|
||||
}
|
||||
}
|
||||
return first
|
||||
}
|
||||
|
||||
// ── Provider interface ──────────────────────────────────────────────────────
|
||||
|
||||
func (p *otelProvider) Tracer(name string) Tracer {
|
||||
tp := p.tp
|
||||
if tp == nil {
|
||||
tp = otel.GetTracerProvider()
|
||||
}
|
||||
return otelTracerBridge{t: tp.Tracer(name)}
|
||||
}
|
||||
|
||||
func (p *otelProvider) Meter(name string) Meter {
|
||||
mp := p.mp
|
||||
if mp == nil {
|
||||
mp = otel.GetMeterProvider()
|
||||
}
|
||||
return otelMeterBridge{m: mp.Meter(name)}
|
||||
}
|
||||
|
||||
func (p *otelProvider) HTTPMiddleware(next http.Handler) http.Handler {
|
||||
if p.mw == nil {
|
||||
return next
|
||||
}
|
||||
return p.mw(next)
|
||||
}
|
||||
|
||||
func (p *otelProvider) PrometheusHandler() http.Handler { return p.promHandler }
|
||||
|
||||
// ── Bridge: Tracer / Span ───────────────────────────────────────────────────
|
||||
|
||||
type otelTracerBridge struct{ t oteltrace.Tracer }
|
||||
|
||||
func (b otelTracerBridge) Start(ctx context.Context, name string, attrs ...Attr) (context.Context, Span) {
|
||||
var opts []oteltrace.SpanStartOption
|
||||
if len(attrs) > 0 {
|
||||
opts = append(opts, oteltrace.WithAttributes(toKVs(attrs)...))
|
||||
}
|
||||
ctx, span := b.t.Start(ctx, name, opts...)
|
||||
return ctx, otelSpanBridge{s: span}
|
||||
}
|
||||
|
||||
type otelSpanBridge struct{ s oteltrace.Span }
|
||||
|
||||
func (b otelSpanBridge) End() { b.s.End() }
|
||||
func (b otelSpanBridge) SetAttributes(attrs ...Attr) { b.s.SetAttributes(toKVs(attrs)...) }
|
||||
func (b otelSpanBridge) RecordError(err error) { b.s.RecordError(err) }
|
||||
|
||||
// ── Bridge: Meter / instruments ─────────────────────────────────────────────
|
||||
|
||||
type otelMeterBridge struct{ m otelmetric.Meter }
|
||||
|
||||
func (b otelMeterBridge) Counter(name, description string) Counter {
|
||||
c, err := b.m.Int64Counter(name, otelmetric.WithDescription(description))
|
||||
if err != nil {
|
||||
return noopCounter{}
|
||||
}
|
||||
return otelCounterBridge{c: c}
|
||||
}
|
||||
|
||||
func (b otelMeterBridge) Histogram(name, description, unit string) Histogram {
|
||||
h, err := b.m.Float64Histogram(name,
|
||||
otelmetric.WithDescription(description),
|
||||
otelmetric.WithUnit(unit),
|
||||
)
|
||||
if err != nil {
|
||||
return noopHistogram{}
|
||||
}
|
||||
return otelHistogramBridge{h: h}
|
||||
}
|
||||
|
||||
func (b otelMeterBridge) Gauge(name, description string) Gauge {
|
||||
g, err := b.m.Float64Gauge(name, otelmetric.WithDescription(description))
|
||||
if err != nil {
|
||||
return noopGauge{}
|
||||
}
|
||||
return otelGaugeBridge{g: g}
|
||||
}
|
||||
|
||||
type otelCounterBridge struct{ c otelmetric.Int64Counter }
|
||||
|
||||
func (b otelCounterBridge) Add(ctx context.Context, delta int64, attrs ...Attr) {
|
||||
b.c.Add(ctx, delta, otelmetric.WithAttributes(toKVs(attrs)...))
|
||||
}
|
||||
|
||||
type otelHistogramBridge struct{ h otelmetric.Float64Histogram }
|
||||
|
||||
func (b otelHistogramBridge) Record(ctx context.Context, value float64, attrs ...Attr) {
|
||||
b.h.Record(ctx, value, otelmetric.WithAttributes(toKVs(attrs)...))
|
||||
}
|
||||
|
||||
type otelGaugeBridge struct{ g otelmetric.Float64Gauge }
|
||||
|
||||
func (b otelGaugeBridge) Set(ctx context.Context, value float64, attrs ...Attr) {
|
||||
b.g.Record(ctx, value, otelmetric.WithAttributes(toKVs(attrs)...))
|
||||
}
|
||||
|
||||
// ── Attribute helpers ───────────────────────────────────────────────────────
|
||||
|
||||
func toKV(a Attr) attribute.KeyValue {
|
||||
switch v := a.Value.(type) {
|
||||
case string:
|
||||
return attribute.String(a.Key, v)
|
||||
case int64:
|
||||
return attribute.Int64(a.Key, v)
|
||||
case int:
|
||||
return attribute.Int(a.Key, v)
|
||||
case float64:
|
||||
return attribute.Float64(a.Key, v)
|
||||
case bool:
|
||||
return attribute.Bool(a.Key, v)
|
||||
default:
|
||||
return attribute.String(a.Key, fmt.Sprintf("%v", v))
|
||||
}
|
||||
}
|
||||
|
||||
func toKVs(attrs []Attr) []attribute.KeyValue {
|
||||
kvs := make([]attribute.KeyValue, 0, len(attrs))
|
||||
for _, a := range attrs {
|
||||
kvs = append(kvs, toKV(a))
|
||||
}
|
||||
return kvs
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user