-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Expand file tree
/
Copy path_otel_utils.py
More file actions
63 lines (53 loc) · 2.13 KB
/
_otel_utils.py
File metadata and controls
63 lines (53 loc) · 2.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
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
62
63
import contextlib
from collections.abc import Iterator
from opentelemetry.trace import Span, SpanKind, Tracer
from mcp import types
from mcp.shared.exceptions import MCPError
@contextlib.contextmanager
def mcp_client_span(
tracer: Tracer,
request: types.ClientRequest | types.ServerRequest | types.ClientNotification | types.ServerNotification,
*,
json_rpc_request_id: int | None = None,
) -> Iterator[Span]:
"""Starts an MCP client span as current span
https://github.com/open-telemetry/semantic-conventions/blob/v1.40.0/docs/gen-ai/mcp.md#client
"""
attributes = {"mcp.method.name": request.method}
# When omitted, the request is treated as a notification. Instrumentations SHOULD NOT
# capture this attribute when the id is null or omitted.
if json_rpc_request_id is not None:
attributes["jsonrpc.request.id"] = str(json_rpc_request_id)
target = None
match request:
case types.CallToolRequest():
target = request.params.name
attributes["gen_ai.tool.name"] = target
attributes["gen_ai.operation.name"] = "execute_tool"
case types.GetPromptRequest():
target = request.params.name
attributes["gen_ai.prompt.name"] = target
case (
types.ReadResourceRequest()
| types.SubscribeRequest()
| types.UnsubscribeRequest()
| types.ResourceUpdatedNotification()
):
attributes["mcp.resource.uri"] = request.params.uri
case _:
pass
if target:
span_name = f"{request.method} {target}"
else:
span_name = request.method
with tracer.start_as_current_span(span_name, kind=SpanKind.CLIENT, attributes=attributes) as span:
try:
yield span
except MCPError as e:
if span.is_recording():
if e.code == types.REQUEST_TIMEOUT:
span.set_attribute("error.type", "timeout")
else:
span.set_attribute("error.type", str(e.code))
span.set_attribute("rpc.response.status_code", str(e.code))
raise