feat(observability): Add metrics, logging, and sync-run core modules
Introduce the foundational observability layer for the sync pipeline: - MetricsLayer: Custom tracing subscriber layer that captures span timing and structured fields, materializing them into a hierarchical Vec<StageTiming> tree for robot-mode performance data output - logging: Dual-layer subscriber infrastructure with configurable stderr verbosity (-v/-vv/-vvv) and always-on JSON file logging with daily rotation and configurable retention (default 30 days) - SyncRunRecorder: Compile-time enforced lifecycle recorder for sync_runs table (start -> succeed|fail), with correlation IDs and aggregate counts - LoggingConfig: New config section for log_dir, retention_days, and file_logging toggle - get_log_dir(): Path helper for log directory resolution - is_permanent_api_error(): Distinguish retryable vs permanent API failures (only 404 is truly permanent; 403/auth errors may be environmental) Database changes: - Migration 013: Add resource_events_synced_for_updated_at watermark columns to issues and merge_requests tables for incremental resource event sync - Migration 014: Enrich sync_runs with run_id correlation ID, aggregate counts (total_items_processed, total_errors), and run_id index - Wrap file-based migrations in savepoints for rollback safety Dependencies: Add uuid (run_id generation), tracing-appender (file logging) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -120,6 +120,41 @@ impl Default for EmbeddingConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Logging and observability settings.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(default)]
|
||||
pub struct LoggingConfig {
|
||||
/// Directory for log files. Default: ~/.local/share/lore/logs/
|
||||
#[serde(rename = "logDir")]
|
||||
pub log_dir: Option<String>,
|
||||
|
||||
/// Days to retain log files. Default: 30. Set to 0 to disable file logging.
|
||||
#[serde(rename = "retentionDays", default = "default_retention_days")]
|
||||
pub retention_days: u32,
|
||||
|
||||
/// Enable JSON log files. Default: true.
|
||||
#[serde(rename = "fileLogging", default = "default_file_logging")]
|
||||
pub file_logging: bool,
|
||||
}
|
||||
|
||||
fn default_retention_days() -> u32 {
|
||||
30
|
||||
}
|
||||
|
||||
fn default_file_logging() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
impl Default for LoggingConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
log_dir: None,
|
||||
retention_days: default_retention_days(),
|
||||
file_logging: default_file_logging(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Main configuration structure.
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct Config {
|
||||
@@ -134,6 +169,9 @@ pub struct Config {
|
||||
|
||||
#[serde(default)]
|
||||
pub embedding: EmbeddingConfig,
|
||||
|
||||
#[serde(default)]
|
||||
pub logging: LoggingConfig,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
|
||||
Reference in New Issue
Block a user