|
6 | 6 | import shutil |
7 | 7 | from dataclasses import dataclass |
8 | 8 | from datetime import datetime |
| 9 | +from enum import Enum |
9 | 10 | from pathlib import Path |
10 | 11 | from typing import Any, Dict, Literal, Optional, List, Tuple |
11 | | -from enum import Enum |
12 | 12 |
|
13 | 13 | from loguru import logger |
14 | 14 | from pydantic import AliasChoices, BaseModel, Field, model_validator |
15 | 15 | from pydantic_settings import BaseSettings, SettingsConfigDict |
16 | 16 |
|
| 17 | +from basic_memory import __version__ |
| 18 | +from basic_memory.telemetry import configure_telemetry |
17 | 19 | from basic_memory.utils import setup_logging, generate_permalink |
18 | 20 |
|
19 | 21 |
|
@@ -140,6 +142,24 @@ class BasicMemoryConfig(BaseSettings): |
140 | 142 | # overridden by ~/.basic-memory/config.json |
141 | 143 | log_level: str = "INFO" |
142 | 144 |
|
| 145 | + # Optional Logfire telemetry (disabled by default) |
| 146 | + logfire_enabled: bool = Field( |
| 147 | + default=False, |
| 148 | + description="Enable Logfire instrumentation for local development or managed deployments.", |
| 149 | + ) |
| 150 | + logfire_send_to_logfire: bool = Field( |
| 151 | + default=False, |
| 152 | + description="When true, allow Logfire to export telemetry to the configured backend.", |
| 153 | + ) |
| 154 | + logfire_service_name: str = Field( |
| 155 | + default="basic-memory", |
| 156 | + description="Base service name used when constructing entrypoint-specific Logfire service names.", |
| 157 | + ) |
| 158 | + logfire_environment: str | None = Field( |
| 159 | + default=None, |
| 160 | + description="Optional override for Logfire environment. Defaults to env when unset.", |
| 161 | + ) |
| 162 | + |
143 | 163 | # Database configuration |
144 | 164 | database_backend: DatabaseBackend = Field( |
145 | 165 | default=DatabaseBackend.SQLITE, |
@@ -955,33 +975,50 @@ def save_basic_memory_config(file_path: Path, config: BasicMemoryConfig) -> None |
955 | 975 | # Logging initialization functions for different entry points |
956 | 976 |
|
957 | 977 |
|
958 | | -def init_cli_logging() -> None: # pragma: no cover |
| 978 | +def _configure_logfire_for_entrypoint(entrypoint: str) -> None: |
| 979 | + """Configure optional Logfire telemetry for a specific entrypoint.""" |
| 980 | + config = ConfigManager().config |
| 981 | + service_name = f"{config.logfire_service_name}-{entrypoint}" |
| 982 | + environment = config.logfire_environment or config.env |
| 983 | + configure_telemetry( |
| 984 | + service_name=service_name, |
| 985 | + environment=environment, |
| 986 | + service_version=__version__, |
| 987 | + enable_logfire=config.logfire_enabled, |
| 988 | + send_to_logfire=config.logfire_send_to_logfire, |
| 989 | + ) |
| 990 | + |
| 991 | + |
| 992 | +def init_cli_logging() -> None: |
959 | 993 | """Initialize logging for CLI commands - file only. |
960 | 994 |
|
961 | 995 | CLI commands should not log to stdout to avoid interfering with |
962 | 996 | command output and shell integration. |
963 | 997 | """ |
964 | 998 | log_level = os.getenv("BASIC_MEMORY_LOG_LEVEL", "INFO") |
| 999 | + _configure_logfire_for_entrypoint("cli") |
965 | 1000 | setup_logging(log_level=log_level, log_to_file=True) |
966 | 1001 |
|
967 | 1002 |
|
968 | | -def init_mcp_logging() -> None: # pragma: no cover |
| 1003 | +def init_mcp_logging() -> None: |
969 | 1004 | """Initialize logging for MCP server - file only. |
970 | 1005 |
|
971 | 1006 | MCP server must not log to stdout as it would corrupt the |
972 | 1007 | JSON-RPC protocol communication. |
973 | 1008 | """ |
974 | 1009 | log_level = os.getenv("BASIC_MEMORY_LOG_LEVEL", "INFO") |
| 1010 | + _configure_logfire_for_entrypoint("mcp") |
975 | 1011 | setup_logging(log_level=log_level, log_to_file=True) |
976 | 1012 |
|
977 | 1013 |
|
978 | | -def init_api_logging() -> None: # pragma: no cover |
| 1014 | +def init_api_logging() -> None: |
979 | 1015 | """Initialize logging for API server. |
980 | 1016 |
|
981 | 1017 | Cloud mode (BASIC_MEMORY_CLOUD_MODE=1): stdout with structured context |
982 | 1018 | Local mode: file only |
983 | 1019 | """ |
984 | 1020 | log_level = os.getenv("BASIC_MEMORY_LOG_LEVEL", "INFO") |
| 1021 | + _configure_logfire_for_entrypoint("api") |
985 | 1022 | cloud_mode = os.getenv("BASIC_MEMORY_CLOUD_MODE", "").lower() in ("1", "true") |
986 | 1023 | if cloud_mode: |
987 | 1024 | setup_logging(log_level=log_level, log_to_stdout=True, structured_context=True) |
|
0 commit comments