Skip to content

Commit 1b39062

Browse files
phernandezclaude
andauthored
refactor(core): rip telemetry wrappers, use logfire directly (#754)
Signed-off-by: phernandez <paul@basicmachines.co> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent c4cf0af commit 1b39062

47 files changed

Lines changed: 1321 additions & 1949 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

pyproject.toml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ dependencies = [
3333
"pyjwt>=2.10.1",
3434
"python-dotenv>=1.1.0",
3535
"pytest-aio>=1.9.0",
36-
"aiofiles>=24.1.0", # Optional observability (disabled by default via config)
36+
"aiofiles>=24.1.0",
3737
"asyncpg>=0.30.0",
3838
"nest-asyncio>=1.6.0", # For Alembic migrations with Postgres
3939
"pytest-asyncio>=1.2.0",
@@ -47,6 +47,7 @@ dependencies = [
4747
"fastembed>=0.7.4",
4848
"sqlite-vec>=0.1.6",
4949
"openai>=1.100.2",
50+
"logfire>=4.19.0",
5051
]
5152

5253
[project.urls]
@@ -58,9 +59,6 @@ Documentation = "https://github.com/basicmachines-co/basic-memory#readme"
5859
basic-memory = "basic_memory.cli.main:app"
5960
bm = "basic_memory.cli.main:app"
6061

61-
[project.optional-dependencies]
62-
telemetry = ["logfire>=4.19.0"]
63-
6462
[build-system]
6563
requires = ["hatchling", "uv-dynamic-versioning>=0.7.0"]
6664
build-backend = "hatchling.build"

src/basic_memory/api/app.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
list_projects,
2626
synchronize_projects,
2727
)
28-
from basic_memory import telemetry
28+
import logfire
2929
from basic_memory.config import init_api_logging
3030
from basic_memory.services.exceptions import EntityAlreadyExistsError
3131
from basic_memory.services.initialization import initialize_app
@@ -44,7 +44,7 @@ async def lifespan(app: FastAPI): # pragma: no cover
4444
set_container(container)
4545
app.state.container = container
4646

47-
with telemetry.operation(
47+
with logfire.span(
4848
"api.lifecycle.startup",
4949
entrypoint="api",
5050
mode=container.mode.name.lower(),
@@ -69,7 +69,7 @@ async def lifespan(app: FastAPI): # pragma: no cover
6969
yield
7070

7171
# Shutdown - coordinator handles clean task cancellation
72-
with telemetry.operation(
72+
with logfire.span(
7373
"api.lifecycle.shutdown",
7474
entrypoint="api",
7575
mode=container.mode.name.lower(),

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

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from fastapi import APIRouter, HTTPException, Response, Path
1414
from loguru import logger
1515

16-
from basic_memory import telemetry
16+
import logfire
1717
from basic_memory.deps import (
1818
EntityServiceV2ExternalDep,
1919
SearchServiceV2ExternalDep,
@@ -74,7 +74,7 @@ async def get_graph(
7474
Returns a flat node/edge structure optimized for rendering with graph libraries.
7575
Only includes resolved relations (where to_id is not null).
7676
"""
77-
with telemetry.operation(
77+
with logfire.span(
7878
"api.request.knowledge.get_graph",
7979
entrypoint="api",
8080
domain="knowledge",
@@ -148,7 +148,7 @@ async def resolve_identifier(
148148
"resolution_method": "permalink"
149149
}
150150
"""
151-
with telemetry.operation(
151+
with logfire.span(
152152
"api.request.knowledge.resolve_entity",
153153
entrypoint="api",
154154
domain="knowledge",
@@ -215,7 +215,7 @@ async def get_entity_by_id(
215215
Raises:
216216
HTTPException: 404 if entity not found
217217
"""
218-
with telemetry.operation(
218+
with logfire.span(
219219
"api.request.knowledge.get_entity",
220220
entrypoint="api",
221221
domain="knowledge",
@@ -255,7 +255,7 @@ async def create_entity(
255255
Returns:
256256
Created entity with generated external_id (UUID) and file content
257257
"""
258-
with telemetry.operation(
258+
with logfire.span(
259259
"api.request.knowledge.create_entity",
260260
entrypoint="api",
261261
domain="knowledge",
@@ -313,7 +313,7 @@ async def update_entity_by_id(
313313
Returns:
314314
Updated entity with file content
315315
"""
316-
with telemetry.operation(
316+
with logfire.span(
317317
"api.request.knowledge.update_entity",
318318
entrypoint="api",
319319
domain="knowledge",
@@ -385,7 +385,7 @@ async def edit_entity_by_id(
385385
Raises:
386386
HTTPException: 404 if entity not found, 400 if edit fails
387387
"""
388-
with telemetry.operation(
388+
with logfire.span(
389389
"api.request.knowledge.edit_entity",
390390
entrypoint="api",
391391
domain="knowledge",
@@ -454,7 +454,7 @@ async def delete_entity_by_id(
454454
455455
Note: Returns deleted=False if entity doesn't exist (idempotent)
456456
"""
457-
with telemetry.operation(
457+
with logfire.span(
458458
"api.request.knowledge.delete_entity",
459459
entrypoint="api",
460460
domain="knowledge",
@@ -503,7 +503,7 @@ async def move_entity(
503503
Returns:
504504
Updated entity with new file path
505505
"""
506-
with telemetry.operation(
506+
with logfire.span(
507507
"api.request.knowledge.move_entity",
508508
entrypoint="api",
509509
domain="knowledge",
@@ -583,7 +583,7 @@ async def move_directory(
583583
Returns:
584584
DirectoryMoveResult with counts and details of moved files
585585
"""
586-
with telemetry.operation(
586+
with logfire.span(
587587
"api.request.knowledge.move_directory",
588588
entrypoint="api",
589589
domain="knowledge",
@@ -647,7 +647,7 @@ async def delete_directory(
647647
Returns:
648648
DirectoryDeleteResult with counts and details of deleted files
649649
"""
650-
with telemetry.operation(
650+
with logfire.span(
651651
"api.request.knowledge.delete_directory",
652652
entrypoint="api",
653653
domain="knowledge",

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

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

12-
from basic_memory import telemetry
12+
import logfire
1313
from basic_memory.deps import ContextServiceV2ExternalDep, EntityRepositoryV2ExternalDep
1414
from basic_memory.schemas.base import TimeFrame, parse_timeframe
1515
from basic_memory.schemas.memory import (
@@ -51,7 +51,7 @@ async def recent(
5151
Returns:
5252
GraphContext with recent activity and related entities
5353
"""
54-
with telemetry.operation(
54+
with logfire.span(
5555
"api.request.memory.recent_activity",
5656
entrypoint="api",
5757
domain="memory",
@@ -72,7 +72,7 @@ async def recent(
7272
limit = page_size
7373
offset = (page - 1) * page_size
7474

75-
with telemetry.scope(
75+
with logfire.span(
7676
"api.memory.recent_activity.build_context",
7777
domain="memory",
7878
action="recent_activity",
@@ -88,7 +88,7 @@ async def recent(
8888
offset=offset,
8989
max_related=max_related,
9090
)
91-
with telemetry.scope(
91+
with logfire.span(
9292
"api.memory.recent_activity.shape_response",
9393
domain="memory",
9494
action="recent_activity",
@@ -137,7 +137,7 @@ async def get_memory_context(
137137
Returns:
138138
GraphContext with the entity and its related context
139139
"""
140-
with telemetry.operation(
140+
with logfire.span(
141141
"api.request.memory.build_context",
142142
entrypoint="api",
143143
domain="memory",
@@ -154,7 +154,7 @@ async def get_memory_context(
154154
limit = page_size
155155
offset = (page - 1) * page_size
156156

157-
with telemetry.scope(
157+
with logfire.span(
158158
"api.memory.build_context.build_context",
159159
domain="memory",
160160
action="build_context",
@@ -170,7 +170,7 @@ async def get_memory_context(
170170
offset=offset,
171171
max_related=max_related,
172172
)
173-
with telemetry.scope(
173+
with logfire.span(
174174
"api.memory.build_context.shape_response",
175175
domain="memory",
176176
action="build_context",

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

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from fastapi import APIRouter, HTTPException, Response, Path
1616
from loguru import logger
1717

18-
from basic_memory import telemetry
18+
import logfire
1919
from basic_memory.deps import (
2020
ProjectConfigV2ExternalDep,
2121
FileServiceV2ExternalDep,
@@ -56,15 +56,15 @@ async def get_resource_content(
5656
Raises:
5757
HTTPException: 404 if entity or file not found
5858
"""
59-
with telemetry.operation(
59+
with logfire.span(
6060
"api.request.resource.get_content",
6161
entrypoint="api",
6262
domain="resource",
6363
action="get_content",
6464
):
6565
logger.debug(f"V2 Getting content for project {project_id}, entity_id: {entity_id}")
6666

67-
with telemetry.scope(
67+
with logfire.span(
6868
"api.resource.get_content.load_entity",
6969
domain="resource",
7070
action="get_content",
@@ -74,7 +74,7 @@ async def get_resource_content(
7474
if not entity:
7575
raise HTTPException(status_code=404, detail=f"Entity {entity_id} not found")
7676

77-
with telemetry.scope(
77+
with logfire.span(
7878
"api.resource.get_content.validate_path",
7979
domain="resource",
8080
action="get_content",
@@ -90,7 +90,7 @@ async def get_resource_content(
9090
detail="Entity contains invalid file path",
9191
)
9292

93-
with telemetry.scope(
93+
with logfire.span(
9494
"api.resource.get_content.ensure_exists",
9595
domain="resource",
9696
action="get_content",
@@ -102,7 +102,7 @@ async def get_resource_content(
102102
detail=f"File not found: {entity.file_path}",
103103
)
104104

105-
with telemetry.scope(
105+
with logfire.span(
106106
"api.resource.get_content.read_content",
107107
domain="resource",
108108
action="get_content",
@@ -139,7 +139,7 @@ async def create_resource(
139139
Raises:
140140
HTTPException: 400 for invalid file paths, 409 if file already exists
141141
"""
142-
with telemetry.operation(
142+
with logfire.span(
143143
"api.request.resource.create",
144144
entrypoint="api",
145145
domain="resource",
@@ -166,7 +166,7 @@ async def create_resource(
166166
f"Use PUT /resource/{existing_entity.external_id} to update it.",
167167
)
168168

169-
with telemetry.scope(
169+
with logfire.span(
170170
"api.resource.create.write_file",
171171
domain="resource",
172172
action="create",
@@ -175,7 +175,7 @@ async def create_resource(
175175
await file_service.ensure_directory(PathLib(data.file_path).parent)
176176
checksum = await file_service.write_file(data.file_path, data.content)
177177

178-
with telemetry.scope(
178+
with logfire.span(
179179
"api.resource.create.read_metadata",
180180
domain="resource",
181181
action="create",
@@ -197,15 +197,15 @@ async def create_resource(
197197
created_at=file_metadata.created_at,
198198
updated_at=file_metadata.modified_at,
199199
)
200-
with telemetry.scope(
200+
with logfire.span(
201201
"api.resource.create.upsert_entity",
202202
domain="resource",
203203
action="create",
204204
phase="upsert_entity",
205205
):
206206
entity = await entity_repository.add(entity)
207207

208-
with telemetry.scope(
208+
with logfire.span(
209209
"api.resource.create.search_index",
210210
domain="resource",
211211
action="create",
@@ -258,7 +258,7 @@ async def update_resource(
258258
Raises:
259259
HTTPException: 404 if entity not found, 400 for invalid paths
260260
"""
261-
with telemetry.operation(
261+
with logfire.span(
262262
"api.request.resource.update",
263263
entrypoint="api",
264264
domain="resource",
@@ -282,7 +282,7 @@ async def update_resource(
282282
"Path must be relative and stay within project boundaries.",
283283
)
284284

285-
with telemetry.scope(
285+
with logfire.span(
286286
"api.resource.update.write_file",
287287
domain="resource",
288288
action="update",
@@ -297,7 +297,7 @@ async def update_resource(
297297

298298
checksum = await file_service.write_file(target_file_path, data.content)
299299

300-
with telemetry.scope(
300+
with logfire.span(
301301
"api.resource.update.read_metadata",
302302
domain="resource",
303303
action="update",
@@ -309,7 +309,7 @@ async def update_resource(
309309
content_type = file_service.content_type(target_file_path)
310310
note_type = "canvas" if target_file_path.endswith(".canvas") else "file"
311311

312-
with telemetry.scope(
312+
with logfire.span(
313313
"api.resource.update.update_entity",
314314
domain="resource",
315315
action="update",
@@ -329,7 +329,7 @@ async def update_resource(
329329
if updated_entity is None:
330330
raise HTTPException(status_code=404, detail=f"Entity {entity_id} not found")
331331

332-
with telemetry.scope(
332+
with logfire.span(
333333
"api.resource.update.search_index",
334334
domain="resource",
335335
action="update",

0 commit comments

Comments
 (0)