Commit a05ccb5
authored
feat: Support spec v1.11.0 — OpenTelemetry OTLP tracing configuration (§4.1.3.6) (#3188)
Implements the `opentelemetry` gateway config section from MCP Gateway
Spec v1.11.0 §4.1.3.6, bridging the gap between the existing
`TracingConfig` skeleton and full spec compliance.
## Config changes
- **New fields on `TracingConfig`**: `Headers map[string]string`,
`TraceID string`, `SpanID string`
- **New TOML key** `[gateway.opentelemetry]` alongside legacy
`[gateway.tracing]` (backward-compatible; `opentelemetry` takes
precedence)
- **JSON stdin**: Added `StdinOpenTelemetryConfig` wired into
`StdinGatewayConfig.opentelemetry`
- **JSON schema**: `opentelemetry` added to `gatewayConfig` definition
with correct types and patterns
```toml
[gateway.opentelemetry]
endpoint = "https://otel-collector.example.com"
trace_id = "4bf92f3577b34da6a3ce929d0e0e4736"
span_id = "00f067aa0ba902b7"
service_name = "mcp-gateway"
[gateway.opentelemetry.headers]
Authorization = "******"
```
## Validation (enforced only for the `opentelemetry` section)
- `endpoint` required and **must be HTTPS**
- `traceId` must be 32-char lowercase hex (or `${VAR}`)
- `spanId` must be 16-char lowercase hex (or `${VAR}`)
- `spanId` without `traceId` → warning, not error
## OTLP provider
- Headers forwarded to exporter via `otlptracehttp.WithHeaders()`
- W3C remote parent context constructed from `traceId`+`spanId` at
startup; missing `spanId` generates a random one (T-OTEL-008)
- `tracing.ParentContext(ctx, cfg)` exported for use at startup
## Instrumentation (`callBackendTool`)
- Span renamed `gateway.tool_call` → `mcp.tool_call`
- Attributes updated to spec names: `mcp.server`, `mcp.method`
(`"tools/call"`), `mcp.tool`
- `http.status_code` attribute added: 200 (success) / 403 (DIFC denied)
/ 500 (error)
## Tests
Compliance tests T-OTEL-001 through T-OTEL-010 covering config
validation, header propagation, W3C traceparent construction, random
span ID generation, and service name defaulting.
> [!WARNING]
>
> <details>
> <summary>Firewall rules blocked me from connecting to one or more
addresses (expand for details)</summary>
>
> #### I tried to connect to the following addresses, but was blocked by
firewall rules:
>
> - `example.com`
> - Triggering command: `/tmp/go-build344646749/b510/launcher.test
/tmp/go-build344646749/b510/launcher.test
-test.testlogfile=/tmp/go-build344646749/b510/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true 0/clients.go
0/doc.go x_amd64/compile OUTPUT -d 168.63.129.16 x_amd64/compile o_.o��
ache/go/1.25.8/x-errorsas oZMU/gIMg3r8eCE3-ifaceassert de/node/bin/as -p
sh -lang=go1.25 646749/b171/_x00-buildtags` (dns block)
> - Triggering command: `/tmp/go-build952104743/b510/launcher.test
/tmp/go-build952104743/b510/launcher.test
-test.testlogfile=/tmp/go-build952104743/b510/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true cmCl2WHYI
646749/b318/ 64/pkg/tool/linux_amd64/vet --gdwarf-5 --64 -o
64/pkg/tool/linux_amd64/vet 6467��
olang.org/grpc@v1.80.0/internal/pretty/pretty.go-p
pkg/mod/github.com/go-logr/logr@v1.4.3/context_smain cfg -b
646749/b318/_cgo/usr/bin/runc p/bin/git
ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile` (dns block)
> - Triggering command: `/tmp/go-build3330052160/b514/launcher.test
/tmp/go-build3330052160/b514/launcher.test
-test.testlogfile=/tmp/go-build3330052160/b514/testlog.txt
-test.paniconexit0 -test.timeout=10m0s e=/t�� t0 m0s x_amd64/vet
pkg/mod/google.ggit ��4.1.3.6) alongside legacy tracing key
- Add StdinOpenTelemetryConfig + wire into ��
ache/go/1.25.8/x--exclude-standard x_amd64/vet --ve�� -o
ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet x_amd64/vet
/tmp/go-build344bash -trimpath 646749/b371/vet.--noprofile x_amd64/vet`
(dns block)
> - `invalid-host-that-does-not-exist-12345.com`
> - Triggering command: `/tmp/go-build344646749/b492/config.test
/tmp/go-build344646749/b492/config.test
-test.testlogfile=/tmp/go-build344646749/b492/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true go t.go
x_amd64/compile` (dns block)
> - Triggering command: `/tmp/go-build952104743/b492/config.test
/tmp/go-build952104743/b492/config.test
-test.testlogfile=/tmp/go-build952104743/b492/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true _.a
646749/b197/vet.cfg 64/pkg/tool/linux_amd64/vet .
ateway/v2/utilitls-files --64 64/pkg/tool/linu--others -I 2mEnnrRfF
646749/b318/ 64/pkg/tool/linux_amd64/vet --gdwarf-5 --64 -o
64/pkg/tool/linusecurity` (dns block)
> - Triggering command: `/tmp/go-build1778975665/b222/config.test
/tmp/go-build1778975665/b222/config.test
-test.testlogfile=/tmp/go-build1778975665/b222/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true
pkg/mod/google.golang.org/grpc@v1.80.0/internal/grpclog/prefix_l-errorsas
-fPIC docker-buildx -pthread -Wl,--no-gc-sectinspect
-fmessage-length--format docker-buildx -o
/tmp/go-build344646749/b370/_pkg_.a -trimpath x_amd64/link -p
google.golang.org/grpc/internal/--version -lang=go1.24 x_amd64/link`
(dns block)
> - `nonexistent.local`
> - Triggering command: `/tmp/go-build344646749/b510/launcher.test
/tmp/go-build344646749/b510/launcher.test
-test.testlogfile=/tmp/go-build344646749/b510/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true 0/clients.go
0/doc.go x_amd64/compile OUTPUT -d 168.63.129.16 x_amd64/compile o_.o��
ache/go/1.25.8/x-errorsas oZMU/gIMg3r8eCE3-ifaceassert de/node/bin/as -p
sh -lang=go1.25 646749/b171/_x00-buildtags` (dns block)
> - Triggering command: `/tmp/go-build952104743/b510/launcher.test
/tmp/go-build952104743/b510/launcher.test
-test.testlogfile=/tmp/go-build952104743/b510/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true cmCl2WHYI
646749/b318/ 64/pkg/tool/linux_amd64/vet --gdwarf-5 --64 -o
64/pkg/tool/linux_amd64/vet 6467��
olang.org/grpc@v1.80.0/internal/pretty/pretty.go-p
pkg/mod/github.com/go-logr/logr@v1.4.3/context_smain cfg -b
646749/b318/_cgo/usr/bin/runc p/bin/git
ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile` (dns block)
> - Triggering command: `/tmp/go-build3330052160/b514/launcher.test
/tmp/go-build3330052160/b514/launcher.test
-test.testlogfile=/tmp/go-build3330052160/b514/testlog.txt
-test.paniconexit0 -test.timeout=10m0s e=/t�� t0 m0s x_amd64/vet
pkg/mod/google.ggit ��4.1.3.6) alongside legacy tracing key
- Add StdinOpenTelemetryConfig + wire into ��
ache/go/1.25.8/x--exclude-standard x_amd64/vet --ve�� -o
ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet x_amd64/vet
/tmp/go-build344bash -trimpath 646749/b371/vet.--noprofile x_amd64/vet`
(dns block)
> - `slow.example.com`
> - Triggering command: `/tmp/go-build344646749/b510/launcher.test
/tmp/go-build344646749/b510/launcher.test
-test.testlogfile=/tmp/go-build344646749/b510/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true 0/clients.go
0/doc.go x_amd64/compile OUTPUT -d 168.63.129.16 x_amd64/compile o_.o��
ache/go/1.25.8/x-errorsas oZMU/gIMg3r8eCE3-ifaceassert de/node/bin/as -p
sh -lang=go1.25 646749/b171/_x00-buildtags` (dns block)
> - Triggering command: `/tmp/go-build952104743/b510/launcher.test
/tmp/go-build952104743/b510/launcher.test
-test.testlogfile=/tmp/go-build952104743/b510/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true cmCl2WHYI
646749/b318/ 64/pkg/tool/linux_amd64/vet --gdwarf-5 --64 -o
64/pkg/tool/linux_amd64/vet 6467��
olang.org/grpc@v1.80.0/internal/pretty/pretty.go-p
pkg/mod/github.com/go-logr/logr@v1.4.3/context_smain cfg -b
646749/b318/_cgo/usr/bin/runc p/bin/git
ache/go/1.25.8/x64/pkg/tool/linux_amd64/compile` (dns block)
> - Triggering command: `/tmp/go-build3330052160/b514/launcher.test
/tmp/go-build3330052160/b514/launcher.test
-test.testlogfile=/tmp/go-build3330052160/b514/testlog.txt
-test.paniconexit0 -test.timeout=10m0s e=/t�� t0 m0s x_amd64/vet
pkg/mod/google.ggit ��4.1.3.6) alongside legacy tracing key
- Add StdinOpenTelemetryConfig + wire into ��
ache/go/1.25.8/x--exclude-standard x_amd64/vet --ve�� -o
ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet x_amd64/vet
/tmp/go-build344bash -trimpath 646749/b371/vet.--noprofile x_amd64/vet`
(dns block)
> - `this-host-does-not-exist-12345.com`
> - Triggering command: `/tmp/go-build344646749/b519/mcp.test
/tmp/go-build344646749/b519/mcp.test
-test.testlogfile=/tmp/go-build344646749/b519/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true 64/src/net -trimpath
64/pkg/tool/linu-nilfunc -p math/rand/v2 -lang=go1.25
64/pkg/tool/linu-buildtags lid_�� 1.10.2/active_he-errorsas
1.10.2/args.go x_amd64/compile 646749/b165/ crypto/rsa ctor
x_amd64/compile` (dns block)
> - Triggering command: `/tmp/go-build952104743/b519/mcp.test
/tmp/go-build952104743/b519/mcp.test
-test.testlogfile=/tmp/go-build952104743/b519/testlog.txt
-test.paniconexit0 -test.timeout=10m0s -test.v=true 646749/b440/_pkg-s
/tmp/go-build344-w cfg go g/grpc/internal//usr/bin/runc
64/pkg/tool/linu--version ache/go/1.25.8/x-extld=gcc -W
646749/b458/_pkg_.a /tmp/go-build344646749/b318/ docker-buildx .
b/gh-aw-mcpg/int/usr/bin/runc --64 docker-buildx` (dns block)
> - Triggering command: `/tmp/go-build3330052160/b523/mcp.test
/tmp/go-build3330052160/b523/mcp.test
-test.testlogfile=/tmp/go-build3330052160/b523/testlog.txt
-test.paniconexit0 -test.timeout=10m0s /usr�� --version
ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet x_amd64/vet g
pkg/mod/google.gls-files ache/go/1.25.8/x--exclude-standard x_amd64/vet
--ve�� -o ache/go/1.25.8/x64/pkg/tool/linux_amd64/vet x_amd64/vet
/tmp/go-build344bash -trimpath docker-buildx x_amd64/vet` (dns block)
>
> If you need me to access, download, or install something from one of
these locations, you can either:
>
> - Configure [Actions setup
steps](https://gh.io/copilot/actions-setup-steps) to set up my
environment, which run before the firewall is enabled
> - Add the appropriate URLs or hosts to the custom allowlist in this
repository's [Copilot coding agent
settings](https://github.com/github/gh-aw-mcpg/settings/copilot/coding_agent)
(admins only)
>
> </details>10 files changed
Lines changed: 1178 additions & 347 deletions
File tree
- internal
- cmd
- config
- schema
- server
- tracing
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
354 | 354 | | |
355 | 355 | | |
356 | 356 | | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
357 | 361 | | |
358 | 362 | | |
359 | 363 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
118 | 118 | | |
119 | 119 | | |
120 | 120 | | |
121 | | - | |
| 121 | + | |
| 122 | + | |
122 | 123 | | |
123 | 124 | | |
124 | 125 | | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
125 | 131 | | |
126 | 132 | | |
127 | 133 | | |
| |||
349 | 355 | | |
350 | 356 | | |
351 | 357 | | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
352 | 373 | | |
353 | 374 | | |
354 | 375 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
32 | 32 | | |
33 | 33 | | |
34 | 34 | | |
35 | | - | |
36 | | - | |
37 | | - | |
38 | | - | |
39 | | - | |
40 | | - | |
41 | | - | |
42 | | - | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
43 | 62 | | |
44 | 63 | | |
45 | 64 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
| 18 | + | |
19 | 19 | | |
20 | | - | |
21 | | - | |
| 20 | + | |
| 21 | + | |
22 | 22 | | |
23 | | - | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
24 | 28 | | |
25 | 29 | | |
26 | | - | |
| 30 | + | |
27 | 31 | | |
28 | 32 | | |
29 | 33 | | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
30 | 50 | | |
31 | 51 | | |
32 | | - | |
| 52 | + | |
33 | 53 | | |
34 | 54 | | |
35 | 55 | | |
36 | 56 | | |
37 | 57 | | |
38 | | - | |
| 58 | + | |
| 59 | + | |
39 | 60 | | |
40 | 61 | | |
41 | 62 | | |
| |||
55 | 76 | | |
56 | 77 | | |
57 | 78 | | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
58 | 100 | | |
0 commit comments