|
| 1 | +// Module included in the following assemblies: |
| 2 | +// |
| 3 | +// *mcp_gateway_config/mcp-gateway-observe.adoc |
| 4 | + |
| 5 | +:_mod-docs-content-type: REFERENCE |
| 6 | +[id="ref-mcp-gateway-router-spans_{context}"] |
| 7 | += {mcpg} router spans for observability |
| 8 | + |
| 9 | +[role="_abstract"] |
| 10 | +When enabled, the MCP router, `ext_proc`, emits trace spans for every request and can export structured logs through {OTELName}. |
| 11 | + |
| 12 | +With traces, you can see one continuous timeline of traffic events across different pods and services. This can help you identify bottlenecks and conduct root-cause analysis. |
| 13 | + |
| 14 | +Spans show one part of the journey. The attributes attached to those spans give you the contextual metadata that you need to have searchable and meaningful traces. The attributes are simple `key: value` pairs attached to each span. |
| 15 | + |
| 16 | +The MCP gateway uses the following router spans: |
| 17 | + |
| 18 | +.MCP router spans |
| 19 | +[cols="1,1,2", options="header"] |
| 20 | +|=== |
| 21 | +|Span |When |Description |
| 22 | + |
| 23 | +|`mcp-router.process` |
| 24 | +|Every `ext_proc` stream |
| 25 | +|Root span. Starts when request headers arrive, ends after response headers are processed. |
| 26 | + |
| 27 | +|`mcp-router.route-decision` |
| 28 | +|The request body is parsed |
| 29 | +|Routing decision: `tool-call` versus pass-through to broker. |
| 30 | + |
| 31 | +|`mcp-router.broker-passthrough` |
| 32 | +|Non-`tool-call` requests |
| 33 | +|Pass-through to broker: `initialize`, `tools/list`, `notifications`. No child spans means the broker is not instrumented. |
| 34 | + |
| 35 | +|`mcp-router.tool-call` |
| 36 | +|`tools/call` requests |
| 37 | +|Full tool call handling including session and server resolution. |
| 38 | + |
| 39 | +|`mcp-router.broker.get-server-info` |
| 40 | +|Inside `tool-call` |
| 41 | +|Call out to broker to resolve which backend server owns the tool. |
| 42 | + |
| 43 | +|`mcp-router.session-cache.get` |
| 44 | +|Inside `tool-call` |
| 45 | +|Call out to session cache to look up an existing backend session. |
| 46 | + |
| 47 | +|`mcp-router.session-init` |
| 48 | +|Cache miss during `tool-call` |
| 49 | +|Hairpin `initialize` request through the gateway to the backend MCP server. |
| 50 | + |
| 51 | +|`mcp-router.session-cache.store` |
| 52 | +|After `session-init` |
| 53 | +|Call out to session cache to store the new backend session. |
| 54 | +|=== |
| 55 | + |
| 56 | +The attributes in the following tables use link:https://opentelemetry.io/docs/specs/semconv/gen-ai/mcp/#server[OpenTelemetry MCP Semantic Conventions]. |
| 57 | + |
| 58 | +.MCP router root span, `mcp-router.process`, attributes |
| 59 | +[cols="1,1,2", options="header"] |
| 60 | +|=== |
| 61 | +|Attribute |Source |Description |
| 62 | + |
| 63 | +|`http.method` |
| 64 | +|`:method` header |
| 65 | +|HTTP method, `POST` |
| 66 | + |
| 67 | +|`http.path` |
| 68 | +|`:path` header |
| 69 | +|Request path, `/mcp` |
| 70 | + |
| 71 | +|`http.request_id` |
| 72 | +|`x-request-id` header |
| 73 | +|Envoy request ID |
| 74 | + |
| 75 | +|`mcp.method.name` |
| 76 | +|JSON-RPC `method` field |
| 77 | +|MCP method, `initialize`, `tools/call`, `tools/list`, and so on |
| 78 | + |
| 79 | +|`gen_ai.tool.name` |
| 80 | +|JSON-RPC `params.name` |
| 81 | +|Tool name, only for `tools/call` |
| 82 | + |
| 83 | +|`jsonrpc.request.id` |
| 84 | +|JSON-RPC `id` field |
| 85 | +|JSON-RPC request ID |
| 86 | + |
| 87 | +|`jsonrpc.protocol.version` |
| 88 | +|JSON-RPC `jsonrpc` field |
| 89 | +|Always "2.0" |
| 90 | + |
| 91 | +|`gen_ai.operation.name` |
| 92 | +|JSON-RPC `method` field |
| 93 | +|Same as `mcp.method.name` |
| 94 | + |
| 95 | +|`mcp.session.id` |
| 96 | +|`mcp-session-id` header |
| 97 | +|Gateway session ID |
| 98 | + |
| 99 | +|`client.address` |
| 100 | +|`x-forwarded-for` header |
| 101 | +|Client IP address |
| 102 | + |
| 103 | +|`http.status_code` |
| 104 | +|`:status` response header |
| 105 | +|Response status code |
| 106 | +|=== |
| 107 | + |
| 108 | +.MCP route decision span, `mcp-router.route-decision`, attributes |
| 109 | +[cols="1,2", options="header"] |
| 110 | +|=== |
| 111 | +|Attribute |Description |
| 112 | + |
| 113 | +|`mcp.method.name` |
| 114 | +|MCP method |
| 115 | + |
| 116 | +|`mcp.route` |
| 117 | +|Routing decision: `tool-call`, `broker`, or `elicitation-response` |
| 118 | +|=== |
| 119 | + |
| 120 | +.MCP tool call span, `mcp-router.tool-call`, attributes |
| 121 | +[cols="1,2", options="header"] |
| 122 | +|=== |
| 123 | +|Attribute |Description |
| 124 | + |
| 125 | +|`gen_ai.tool.name` |
| 126 | +|Tool name from the request |
| 127 | + |
| 128 | +|`mcp.session.id` |
| 129 | +|Gateway session ID |
| 130 | + |
| 131 | +|`mcp.server` |
| 132 | +|Resolved backend server name |
| 133 | + |
| 134 | +|`mcp.server.hostname` |
| 135 | +|Resolved backend server hostname |
| 136 | +|=== |
| 137 | + |
| 138 | +.MCP error attributes |
| 139 | +[cols="1,2", options="header"] |
| 140 | +|=== |
| 141 | +|Attribute |Description |
| 142 | + |
| 143 | +|`error.type` |
| 144 | +|Error classification, such as `tool_not_found`, `missing_tool_name`, `invalid_session`, `session_cache_error`, `session_init_error`, `marshal_error`, `path_parse_error` |
| 145 | + |
| 146 | +|`error_source` |
| 147 | +|Component that generated the error, such as`ext-proc` |
| 148 | + |
| 149 | +|`http.status_code` |
| 150 | +|HTTP status code returned |
| 151 | +|=== |
| 152 | + |
| 153 | +When there is an error, spans include these attributes. |
0 commit comments