feat: configure logfire telemetry (#12) · basicmachines-co/basic-memory@6da1438 · GitHub
Skip to content

Commit 6da1438

Browse files
phernandezphernandez
andauthored
feat: configure logfire telemetry (#12)
Co-authored-by: phernandez <phernandez@basicmachines.co>
1 parent a6b4690 commit 6da1438

10 files changed

Lines changed: 487 additions & 14 deletions

File tree

Makefile

Lines changed: 2 additions & 2 deletions

installer/installer.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,14 @@ def update_claude_config():
4949
config = {"mcpServers": {}}
5050

5151
# Add/update basic-memory config
52-
config["mcpServers"]["basic-memory"] = {"command": "uvx", "args": ["basic-memory", "mcp"]}
52+
config["mcpServers"]["basic-memory"] = {
53+
"command": "uvx",
54+
"args": ["basic-memory@latest", "mcp"],
55+
"env": {
56+
"BASIC_MEMORY_ENV": "user",
57+
"LOGFIRE_TOKEN": "n2Fpvn34LjKYq8TdF1ZrXMgdBPXGn4HfXy6tYghZ55dB",
58+
},
59+
}
5360

5461
# Write back config
5562
config_path.write_text(json.dumps(config, indent=2))

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ dependencies = [
2929
"fastapi[standard]>=0.115.8",
3030
"alembic>=1.14.1",
3131
"qasync>=0.27.1",
32+
"logfire[fastapi,sqlalchemy,sqlite3]>=3.6.0",
3233
]
3334

3435

src/basic_memory/api/app.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from contextlib import asynccontextmanager
44

5+
import logfire
56
from fastapi import FastAPI, HTTPException
67
from fastapi.exception_handlers import http_exception_handler
78
from loguru import logger
@@ -10,11 +11,13 @@
1011
from basic_memory import db
1112
from basic_memory.config import config as app_config
1213
from basic_memory.api.routers import knowledge, search, memory, resource
14+
from basic_memory.utils import setup_logging
1315

1416

1517
@asynccontextmanager
1618
async def lifespan(app: FastAPI): # pragma: no cover
1719
"""Lifecycle manager for the FastAPI app."""
20+
setup_logging(log_file=".basic-memory/basic-memory.log")
1821
logger.info(f"Starting Basic Memory API {basic_memory.__version__}")
1922
await db.run_migrations(app_config)
2023
yield
@@ -30,6 +33,10 @@ async def lifespan(app: FastAPI): # pragma: no cover
3033
lifespan=lifespan,
3134
)
3235

36+
if app_config != "test":
37+
logfire.instrument_fastapi(app)
38+
39+
3340
# Include routers
3441
app.include_router(knowledge.router)
3542
app.include_router(search.router)

src/basic_memory/cli/main.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
"""Main CLI entry point for basic-memory.""" # pragma: no cover
22

33
from basic_memory.cli.app import app # pragma: no cover
4-
from basic_memory.utils import setup_logging # pragma: no cover
54

65
# Register commands
76
from basic_memory.cli.commands import ( # noqa: F401 # pragma: no cover
@@ -16,8 +15,5 @@
1615
)
1716

1817

19-
# Set up logging when module is imported
20-
setup_logging(log_file=".basic-memory/basic-memory-cli.log") # pragma: no cover
21-
2218
if __name__ == "__main__": # pragma: no cover
2319
app()

src/basic_memory/config.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
"""Configuration management for basic-memory."""
22

33
from pathlib import Path
4+
from typing import Literal
45

56
from pydantic import Field, field_validator
67
from pydantic_settings import BaseSettings, SettingsConfigDict
78

89
DATABASE_NAME = "memory.db"
910
DATA_DIR_NAME = ".basic-memory"
1011

12+
Environment = Literal["test", "dev", "prod"]
13+
1114

1215
class ProjectConfig(BaseSettings):
1316
"""Configuration for a specific basic-memory project."""
1417

18+
env: Environment = Field(default="dev", description="Environment name")
19+
1520
# Default to ~/basic-memory but allow override with env var: BASIC_MEMORY_HOME
1621
home: Path = Field(
1722
default_factory=lambda: Path.home() / "basic-memory",

src/basic_memory/utils.py

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,11 @@
99
from loguru import logger
1010
from unidecode import unidecode
1111

12+
import basic_memory
1213
from basic_memory.config import config
1314

15+
import logfire
16+
1417

1518
def generate_permalink(file_path: Union[Path, str]) -> str:
1619
"""Generate a stable permalink from a file path.
@@ -61,19 +64,45 @@ def generate_permalink(file_path: Union[Path, str]) -> str:
6164
return "/".join(clean_segments)
6265

6366

64-
def setup_logging(home_dir: Path = config.home, log_file: Optional[str] = None) -> None:
67+
def setup_logging(
68+
home_dir: Path = config.home, log_file: Optional[str] = None
69+
) -> None: # pragma: no cover
6570
"""
6671
Configure logging for the application.
72+
:param home_dir: the root directory for the application
73+
:param log_file: the name of the log file to write to
74+
:param app: the fastapi application instance
6775
"""
6876

6977
# Remove default handler and any existing handlers
7078
logger.remove()
7179

72-
# Add file handler
73-
if log_file:
80+
# Add file handler if we are not running tests
81+
if log_file and config.env != "test":
82+
# enable pydantic logfire
83+
logfire.configure(
84+
code_source=logfire.CodeSource(
85+
repository="https://github.com/basicmachines-co/basic-memory",
86+
revision=basic_memory.__version__,
87+
root_path="/src/basic_memory",
88+
),
89+
environment=config.env,
90+
)
91+
logger.configure(handlers=[logfire.loguru_handler()])
92+
93+
# instrument code spans
94+
logfire.instrument_sqlite3()
95+
logfire.instrument_pydantic()
96+
97+
from basic_memory.db import _engine as engine
98+
99+
if engine:
100+
logfire.instrument_sqlalchemy(engine=engine)
101+
102+
# setup logger
74103
log_path = home_dir / log_file
75104
logger.add(
76-
str(log_path), # loguru expects a string path
105+
str(log_path),
77106
level=config.log_level,
78107
rotation="100 MB",
79108
retention="10 days",
@@ -85,3 +114,5 @@ def setup_logging(home_dir: Path = config.home, log_file: Optional[str] = None)
85114

86115
# Add stderr handler
87116
logger.add(sys.stderr, level=config.log_level, backtrace=True, diagnose=True, colorize=True)
117+
118+
logger.info(f"ENV: '{config.env}' Log level: '{config.log_level}' Logging to {log_file}")

tests/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from basic_memory.config import config
2+
3+
# set config.env to "test" for pytest to prevent logging to file in utils.setup_logging()
4+
config.env = "test"

tests/test_basic_memory.py

Lines changed: 41 additions & 2 deletions

0 commit comments

Comments
 (0)