feat: configure logfire telemetry (#12)

Co-authored-by: phernandez <phernandez@basicmachines.co>
This commit is contained in:
Paul Hernandez
2025-02-18 15:53:38 -06:00
committed by GitHub
parent a6b46908b1
commit 6da143898b
10 changed files with 487 additions and 14 deletions
+7
View File
@@ -2,6 +2,7 @@
from contextlib import asynccontextmanager
import logfire
from fastapi import FastAPI, HTTPException
from fastapi.exception_handlers import http_exception_handler
from loguru import logger
@@ -10,11 +11,13 @@ import basic_memory
from basic_memory import db
from basic_memory.config import config as app_config
from basic_memory.api.routers import knowledge, search, memory, resource
from basic_memory.utils import setup_logging
@asynccontextmanager
async def lifespan(app: FastAPI): # pragma: no cover
"""Lifecycle manager for the FastAPI app."""
setup_logging(log_file=".basic-memory/basic-memory.log")
logger.info(f"Starting Basic Memory API {basic_memory.__version__}")
await db.run_migrations(app_config)
yield
@@ -30,6 +33,10 @@ app = FastAPI(
lifespan=lifespan,
)
if app_config != "test":
logfire.instrument_fastapi(app)
# Include routers
app.include_router(knowledge.router)
app.include_router(search.router)
-4
View File
@@ -1,7 +1,6 @@
"""Main CLI entry point for basic-memory.""" # pragma: no cover
from basic_memory.cli.app import app # pragma: no cover
from basic_memory.utils import setup_logging # pragma: no cover
# Register commands
from basic_memory.cli.commands import ( # noqa: F401 # pragma: no cover
@@ -16,8 +15,5 @@ from basic_memory.cli.commands import ( # noqa: F401 # pragma: no cover
)
# Set up logging when module is imported
setup_logging(log_file=".basic-memory/basic-memory-cli.log") # pragma: no cover
if __name__ == "__main__": # pragma: no cover
app()
+5
View File
@@ -1,6 +1,7 @@
"""Configuration management for basic-memory."""
from pathlib import Path
from typing import Literal
from pydantic import Field, field_validator
from pydantic_settings import BaseSettings, SettingsConfigDict
@@ -8,10 +9,14 @@ from pydantic_settings import BaseSettings, SettingsConfigDict
DATABASE_NAME = "memory.db"
DATA_DIR_NAME = ".basic-memory"
Environment = Literal["test", "dev", "prod"]
class ProjectConfig(BaseSettings):
"""Configuration for a specific basic-memory project."""
env: Environment = Field(default="dev", description="Environment name")
# Default to ~/basic-memory but allow override with env var: BASIC_MEMORY_HOME
home: Path = Field(
default_factory=lambda: Path.home() / "basic-memory",
+35 -4
View File
@@ -9,8 +9,11 @@ from typing import Optional, Union
from loguru import logger
from unidecode import unidecode
import basic_memory
from basic_memory.config import config
import logfire
def generate_permalink(file_path: Union[Path, str]) -> str:
"""Generate a stable permalink from a file path.
@@ -61,19 +64,45 @@ def generate_permalink(file_path: Union[Path, str]) -> str:
return "/".join(clean_segments)
def setup_logging(home_dir: Path = config.home, log_file: Optional[str] = None) -> None:
def setup_logging(
home_dir: Path = config.home, log_file: Optional[str] = None
) -> None: # pragma: no cover
"""
Configure logging for the application.
:param home_dir: the root directory for the application
:param log_file: the name of the log file to write to
:param app: the fastapi application instance
"""
# Remove default handler and any existing handlers
logger.remove()
# Add file handler
if log_file:
# Add file handler if we are not running tests
if log_file and config.env != "test":
# enable pydantic logfire
logfire.configure(
code_source=logfire.CodeSource(
repository="https://github.com/basicmachines-co/basic-memory",
revision=basic_memory.__version__,
root_path="/src/basic_memory",
),
environment=config.env,
)
logger.configure(handlers=[logfire.loguru_handler()])
# instrument code spans
logfire.instrument_sqlite3()
logfire.instrument_pydantic()
from basic_memory.db import _engine as engine
if engine:
logfire.instrument_sqlalchemy(engine=engine)
# setup logger
log_path = home_dir / log_file
logger.add(
str(log_path), # loguru expects a string path
str(log_path),
level=config.log_level,
rotation="100 MB",
retention="10 days",
@@ -85,3 +114,5 @@ def setup_logging(home_dir: Path = config.home, log_file: Optional[str] = None)
# Add stderr handler
logger.add(sys.stderr, level=config.log_level, backtrace=True, diagnose=True, colorize=True)
logger.info(f"ENV: '{config.env}' Log level: '{config.log_level}' Logging to {log_file}")