Skip to content

Commit ab7d023

Browse files
authored
fix: add tests for telemetry (#31)
1 parent acf25ef commit ab7d023

File tree

4 files changed

+65
-52
lines changed

4 files changed

+65
-52
lines changed

src/mcp_server_datahub/__main__.py

Lines changed: 1 addition & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,17 @@
11
import logging
2-
from typing import Any
32

43
import click
5-
import mcp.types as mt
64
from datahub.ingestion.graph.config import ClientMode
75
from datahub.sdk.main_client import DataHubClient
86
from datahub.telemetry import telemetry
9-
from datahub.utilities.perf_timer import PerfTimer
10-
from fastmcp.server.middleware import CallNext, Middleware, MiddlewareContext
117
from fastmcp.server.middleware.logging import LoggingMiddleware
128
from typing_extensions import Literal
139

10+
from mcp_server_datahub._telemetry import TelemetryMiddleware
1411
from mcp_server_datahub._version import __version__
1512
from mcp_server_datahub.mcp_server import mcp, with_datahub_client
1613

1714
logging.basicConfig(level=logging.INFO)
18-
telemetry.telemetry_instance.add_global_property(
19-
"mcp_server_datahub_version", __version__
20-
)
21-
22-
logger = logging.getLogger(__name__)
23-
24-
25-
class TelemetryMiddleware(Middleware):
26-
"""Middleware that logs tool calls."""
27-
28-
async def on_call_tool(
29-
self,
30-
context: MiddlewareContext[mt.CallToolRequestParams],
31-
call_next: CallNext[mt.CallToolRequestParams, mt.CallToolResult],
32-
) -> mt.CallToolResult:
33-
telemetry_data: dict[str, Any] = {}
34-
with PerfTimer() as timer:
35-
telemetry_data = {
36-
"tool": context.message.name,
37-
"source": context.source,
38-
"type": context.type,
39-
"method": context.method,
40-
}
41-
try:
42-
result = await call_next(context)
43-
44-
# BUG: The FastMCP type annotations seem to be incorrect.
45-
# This method typically returns fastmcp.tools.tool.ToolResult.
46-
if isinstance(result, mt.CallToolResult):
47-
telemetry_data["tool_result_is_error"] = result.isError
48-
telemetry_data["tool_result_length"] = (
49-
sum(
50-
len(block.text)
51-
for block in result.content
52-
if isinstance(block, mt.TextContent)
53-
),
54-
)
55-
56-
return result
57-
58-
except Exception as e:
59-
telemetry_data["tool_call_error"] = e.__class__.__name__
60-
raise
61-
finally:
62-
telemetry_data["duration_seconds"] = timer.elapsed_seconds()
63-
telemetry.telemetry_instance.ping(
64-
"mcp-server-tool-call", telemetry_data
65-
)
6615

6716

6817
@click.command()

src/mcp_server_datahub/_telemetry.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from typing import Any
2+
3+
import mcp.types as mt
4+
from datahub.telemetry import telemetry
5+
from datahub.utilities.perf_timer import PerfTimer
6+
from fastmcp.server.middleware import CallNext, Middleware, MiddlewareContext
7+
8+
from mcp_server_datahub._version import __version__
9+
10+
telemetry.telemetry_instance.add_global_property(
11+
"mcp_server_datahub_version", __version__
12+
)
13+
14+
15+
class TelemetryMiddleware(Middleware):
16+
"""Middleware that logs tool calls."""
17+
18+
async def on_call_tool(
19+
self,
20+
context: MiddlewareContext[mt.CallToolRequestParams],
21+
call_next: CallNext[mt.CallToolRequestParams, mt.CallToolResult],
22+
) -> mt.CallToolResult:
23+
telemetry_data: dict[str, Any] = {}
24+
with PerfTimer() as timer:
25+
telemetry_data = {
26+
"tool": context.message.name,
27+
"source": context.source,
28+
"type": context.type,
29+
"method": context.method,
30+
}
31+
try:
32+
result = await call_next(context)
33+
34+
# BUG: The FastMCP type annotations seem to be incorrect.
35+
# This method typically returns fastmcp.tools.tool.ToolResult.
36+
if isinstance(result, mt.CallToolResult):
37+
telemetry_data["tool_result_is_error"] = result.isError
38+
telemetry_data["tool_result_length"] = (
39+
sum(
40+
len(block.text)
41+
for block in result.content
42+
if isinstance(block, mt.TextContent)
43+
),
44+
)
45+
46+
return result
47+
48+
except Exception as e:
49+
telemetry_data["tool_call_error"] = e.__class__.__name__
50+
raise
51+
finally:
52+
telemetry_data["duration_seconds"] = timer.elapsed_seconds()
53+
telemetry.telemetry_instance.ping(
54+
"mcp-server-tool-call", telemetry_data
55+
)

tests/conftest.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
import os
2+
13
import pytest
24

5+
os.environ["DATAHUB_TELEMETRY_ENABLED"] = "false"
6+
37

48
@pytest.fixture
59
def anyio_backend() -> str:

tests/test_mcp_server.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from datahub.sdk.main_client import DataHubClient
66
from fastmcp import Client
77

8+
from mcp_server_datahub._telemetry import TelemetryMiddleware
89
from mcp_server_datahub.mcp_server import (
910
get_dataset_queries,
1011
get_entity,
@@ -16,6 +17,10 @@
1617
_test_urn = "urn:li:dataset:(urn:li:dataPlatform:snowflake,long_tail_companions.analytics.pet_details,PROD)"
1718
_test_domain = "urn:li:domain:0da1ef03-8870-45db-9f47-ef4f592f095c"
1819

20+
# Add telemetry middleware to the MCP server.
21+
# This way our tests also validate that the telemetry generation does not break anything else.
22+
mcp.add_middleware(TelemetryMiddleware())
23+
1924

2025
@pytest.fixture(autouse=True, scope="session")
2126
def setup_client() -> Iterable[None]:

0 commit comments

Comments
 (0)