Skip to content

Commit 98a2a3c

Browse files
committed
Unify MCP telemetry spans across routers and services
Signed-off-by: phernandez <paul@basicmachines.co>
1 parent 01cbad1 commit 98a2a3c

28 files changed

Lines changed: 2633 additions & 1312 deletions

src/basic_memory/api/v2/routers/knowledge_router.py

Lines changed: 348 additions & 182 deletions
Large diffs are not rendered by default.

src/basic_memory/api/v2/routers/memory_router.py

Lines changed: 93 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from fastapi import APIRouter, Query, Path
1010
from loguru import logger
1111

12+
from basic_memory import telemetry
1213
from basic_memory.deps import ContextServiceV2ExternalDep, EntityRepositoryV2ExternalDep
1314
from basic_memory.schemas.base import TimeFrame, parse_timeframe
1415
from basic_memory.schemas.memory import (
@@ -50,30 +51,55 @@ async def recent(
5051
Returns:
5152
GraphContext with recent activity and related entities
5253
"""
53-
# return all types by default
54-
types = (
55-
[SearchItemType.ENTITY, SearchItemType.RELATION, SearchItemType.OBSERVATION]
56-
if not type
57-
else type
58-
)
59-
60-
logger.debug(
61-
f"V2 Getting recent context for project {project_id}: `{types}` depth: `{depth}` timeframe: `{timeframe}` page: `{page}` page_size: `{page_size}` max_related: `{max_related}`"
62-
)
63-
# Parse timeframe
64-
since = parse_timeframe(timeframe)
65-
limit = page_size
66-
offset = (page - 1) * page_size
67-
68-
# Build context
69-
context = await context_service.build_context(
70-
types=types, depth=depth, since=since, limit=limit, offset=offset, max_related=max_related
71-
)
72-
recent_context = await to_graph_context(
73-
context, entity_repository=entity_repository, page=page, page_size=page_size
74-
)
75-
logger.debug(f"V2 Recent context: {recent_context.model_dump_json()}")
76-
return recent_context
54+
with telemetry.operation(
55+
"api.request.memory.recent_activity",
56+
entrypoint="api",
57+
domain="memory",
58+
action="recent_activity",
59+
page=page,
60+
page_size=page_size,
61+
):
62+
types = (
63+
[SearchItemType.ENTITY, SearchItemType.RELATION, SearchItemType.OBSERVATION]
64+
if not type
65+
else type
66+
)
67+
68+
logger.debug(
69+
f"V2 Getting recent context for project {project_id}: `{types}` depth: `{depth}` timeframe: `{timeframe}` page: `{page}` page_size: `{page_size}` max_related: `{max_related}`"
70+
)
71+
since = parse_timeframe(timeframe)
72+
limit = page_size
73+
offset = (page - 1) * page_size
74+
75+
with telemetry.scope(
76+
"api.memory.recent_activity.build_context",
77+
domain="memory",
78+
action="recent_activity",
79+
phase="build_context",
80+
page=page,
81+
page_size=page_size,
82+
):
83+
context = await context_service.build_context(
84+
types=types,
85+
depth=depth,
86+
since=since,
87+
limit=limit,
88+
offset=offset,
89+
max_related=max_related,
90+
)
91+
with telemetry.scope(
92+
"api.memory.recent_activity.shape_response",
93+
domain="memory",
94+
action="recent_activity",
95+
phase="shape_response",
96+
result_count=len(context.results),
97+
):
98+
recent_context = await to_graph_context(
99+
context, entity_repository=entity_repository, page=page, page_size=page_size
100+
)
101+
logger.debug(f"V2 Recent context: {recent_context.model_dump_json()}")
102+
return recent_context
77103

78104

79105
# get_memory_context needs to be declared last so other paths can match
@@ -111,20 +137,46 @@ async def get_memory_context(
111137
Returns:
112138
GraphContext with the entity and its related context
113139
"""
114-
logger.debug(
115-
f"V2 Getting context for project {project_id}, URI: `{uri}` depth: `{depth}` timeframe: `{timeframe}` page: `{page}` page_size: `{page_size}` max_related: `{max_related}`"
116-
)
117-
memory_url = normalize_memory_url(uri)
118-
119-
# Parse timeframe
120-
since = parse_timeframe(timeframe) if timeframe else None
121-
limit = page_size
122-
offset = (page - 1) * page_size
123-
124-
# Build context
125-
context = await context_service.build_context(
126-
memory_url, depth=depth, since=since, limit=limit, offset=offset, max_related=max_related
127-
)
128-
return await to_graph_context(
129-
context, entity_repository=entity_repository, page=page, page_size=page_size
130-
)
140+
with telemetry.operation(
141+
"api.request.memory.build_context",
142+
entrypoint="api",
143+
domain="memory",
144+
action="build_context",
145+
page=page,
146+
page_size=page_size,
147+
):
148+
logger.debug(
149+
f"V2 Getting context for project {project_id}, URI: `{uri}` depth: `{depth}` timeframe: `{timeframe}` page: `{page}` page_size: `{page_size}` max_related: `{max_related}`"
150+
)
151+
memory_url = normalize_memory_url(uri)
152+
153+
since = parse_timeframe(timeframe) if timeframe else None
154+
limit = page_size
155+
offset = (page - 1) * page_size
156+
157+
with telemetry.scope(
158+
"api.memory.build_context.build_context",
159+
domain="memory",
160+
action="build_context",
161+
phase="build_context",
162+
page=page,
163+
page_size=page_size,
164+
):
165+
context = await context_service.build_context(
166+
memory_url,
167+
depth=depth,
168+
since=since,
169+
limit=limit,
170+
offset=offset,
171+
max_related=max_related,
172+
)
173+
with telemetry.scope(
174+
"api.memory.build_context.shape_response",
175+
domain="memory",
176+
action="build_context",
177+
phase="shape_response",
178+
result_count=len(context.results),
179+
):
180+
return await to_graph_context(
181+
context, entity_repository=entity_repository, page=page, page_size=page_size
182+
)

0 commit comments

Comments
 (0)