···11+-- Main log entries table with comprehensive structured fields
22+CREATE TABLE IF NOT EXISTS logs (
33+ id INTEGER PRIMARY KEY AUTOINCREMENT,
44+55+ -- Core fields
66+ timestamp REAL NOT NULL, -- Unix timestamp with microseconds
77+ level INTEGER NOT NULL, -- 0=App, 1=Error, 2=Warning, 3=Info, 4=Debug
88+ source TEXT NOT NULL, -- Module/source name (e.g., 'myapp.db.connection')
99+ message TEXT NOT NULL, -- Full log message, no truncation
1010+1111+ -- Error classification
1212+ error_type TEXT, -- Exception name or error classification
1313+ error_code TEXT, -- Specific error code if applicable
1414+ error_hash TEXT, -- Hash for grouping similar errors
1515+ stack_trace TEXT, -- Full stack trace
1616+1717+ -- Execution context
1818+ pid INTEGER, -- Process ID
1919+ ppid INTEGER, -- Parent process ID
2020+ thread_id TEXT, -- Thread/fiber ID for Eio
2121+ fiber_id TEXT, -- Specific Eio fiber ID
2222+ domain_id INTEGER, -- OCaml domain ID for multicore
2323+2424+ -- Request/Session tracking
2525+ session_id TEXT, -- Session identifier
2626+ request_id TEXT, -- Request identifier
2727+ trace_id TEXT, -- Distributed tracing ID
2828+ span_id TEXT, -- Span ID for tracing
2929+ parent_span_id TEXT, -- Parent span for trace hierarchy
3030+3131+ -- Source location
3232+ file_path TEXT, -- Full file path
3333+ file_name TEXT, -- Just the filename
3434+ line_number INTEGER, -- Line number in source
3535+ column_number INTEGER, -- Column number if available
3636+ function_name TEXT, -- Function/method name
3737+ module_path TEXT, -- Full module path (e.g., 'Myapp.Db.Connection')
3838+3939+ -- Performance metrics
4040+ duration_ms REAL, -- Operation duration in milliseconds
4141+ memory_before INTEGER, -- Memory usage before operation (bytes)
4242+ memory_after INTEGER, -- Memory usage after operation (bytes)
4343+ memory_delta INTEGER, -- Memory change
4444+ cpu_time_ms REAL, -- CPU time consumed
4545+4646+ -- Network context
4747+ client_ip TEXT, -- Client IP address
4848+ server_ip TEXT, -- Server IP address
4949+ host_name TEXT, -- Hostname
5050+ port INTEGER, -- Port number
5151+ protocol TEXT, -- Protocol (HTTP, gRPC, etc.)
5252+ method TEXT, -- HTTP method or RPC method
5353+ path TEXT, -- Request path or endpoint
5454+ status_code INTEGER, -- Response status code
5555+ bytes_sent INTEGER, -- Bytes sent
5656+ bytes_received INTEGER, -- Bytes received
5757+5858+ -- User context
5959+ user_id TEXT, -- User identifier
6060+ tenant_id TEXT, -- Tenant ID for multi-tenant apps
6161+ organization_id TEXT, -- Organization ID
6262+6363+ -- System context
6464+ os_name TEXT, -- Operating system name
6565+ os_version TEXT, -- OS version
6666+ ocaml_version TEXT, -- OCaml compiler version
6767+ app_version TEXT, -- Application version
6868+ environment TEXT, -- Environment (dev, staging, prod)
6969+ region TEXT, -- Deployment region
7070+ container_id TEXT, -- Docker/container ID
7171+ k8s_pod TEXT, -- Kubernetes pod name
7272+ k8s_namespace TEXT, -- Kubernetes namespace
7373+7474+ -- Metadata fields (JSON for flexibility)
7575+ tags TEXT, -- JSON array of tags
7676+ labels TEXT, -- JSON object of key-value labels
7777+ context TEXT, -- JSON object with arbitrary context
7878+ custom_fields TEXT, -- JSON object for app-specific fields
7979+8080+ -- Audit fields
8181+ created_at REAL DEFAULT (julianday('now')),
8282+ indexed_at REAL -- When added to FTS index
8383+);
8484+8585+-- Full-text search index on all text fields
8686+CREATE VIRTUAL TABLE IF NOT EXISTS logs_fts USING fts5(
8787+ message,
8888+ error_type,
8989+ error_code,
9090+ source,
9191+ file_path,
9292+ function_name,
9393+ module_path,
9494+ path,
9595+ method,
9696+ stack_trace,
9797+ tags,
9898+ labels,
9999+ context,
100100+ custom_fields,
101101+ content=logs,
102102+ content_rowid=id,
103103+ tokenize='porter unicode61'
104104+);
105105+106106+-- Pattern tracking for error analysis
107107+CREATE TABLE IF NOT EXISTS patterns (
108108+ id INTEGER PRIMARY KEY AUTOINCREMENT,
109109+ pattern_hash TEXT UNIQUE NOT NULL, -- Hash of normalized pattern
110110+ pattern TEXT NOT NULL, -- Normalized pattern template
111111+ pattern_type TEXT, -- Type of pattern (error, warning, anomaly)
112112+113113+ -- Occurrence tracking
114114+ first_seen REAL NOT NULL,
115115+ last_seen REAL NOT NULL,
116116+ occurrence_count INTEGER DEFAULT 1,
117117+ unique_sources INTEGER DEFAULT 1, -- Number of unique sources
118118+ unique_sessions INTEGER DEFAULT 1, -- Number of unique sessions affected
119119+120120+ -- Statistical analysis
121121+ avg_duration_ms REAL, -- Average duration when this occurs
122122+ max_duration_ms REAL, -- Maximum duration observed
123123+ min_duration_ms REAL, -- Minimum duration observed
124124+125125+ -- Trend analysis
126126+ hourly_rate REAL, -- Occurrences per hour
127127+ daily_rate REAL, -- Occurrences per day
128128+ acceleration_rate REAL, -- Rate of increase/decrease
129129+130130+ -- Claude consultation tracking
131131+ severity_score REAL, -- Calculated severity (0-10)
132132+ impact_score REAL, -- Business impact score
133133+ last_consultation REAL, -- When Claude last reviewed
134134+ consultation_count INTEGER DEFAULT 0, -- Number of consultations
135135+ fix_attempted BOOLEAN DEFAULT 0, -- Whether a fix was attempted
136136+ fix_successful BOOLEAN DEFAULT 0, -- Whether the fix worked
137137+138138+ -- Metadata
139139+ sample_log_ids TEXT, -- JSON array of example log IDs
140140+ related_patterns TEXT, -- JSON array of related pattern IDs
141141+ notes TEXT, -- Human or Claude notes
142142+143143+ created_at REAL DEFAULT (julianday('now')),
144144+ updated_at REAL DEFAULT (julianday('now'))
145145+);
146146+147147+-- Time-series data for pattern analysis
148148+CREATE TABLE IF NOT EXISTS pattern_metrics (
149149+ pattern_id INTEGER REFERENCES patterns(id) ON DELETE CASCADE,
150150+ timestamp REAL NOT NULL, -- Bucket timestamp (e.g., hour boundary)
151151+ bucket_size INTEGER NOT NULL, -- Bucket size in seconds (3600 for hourly)
152152+153153+ -- Metrics for this time bucket
154154+ occurrence_count INTEGER DEFAULT 0,
155155+ unique_sources INTEGER DEFAULT 0,
156156+ unique_sessions INTEGER DEFAULT 0,
157157+ avg_duration_ms REAL,
158158+ max_duration_ms REAL,
159159+ error_rate REAL, -- Errors per second in this bucket
160160+161161+ PRIMARY KEY (pattern_id, timestamp, bucket_size)
162162+);
163163+164164+-- Session tracking for correlation
165165+CREATE TABLE IF NOT EXISTS sessions (
166166+ session_id TEXT PRIMARY KEY,
167167+ start_time REAL NOT NULL,
168168+ end_time REAL,
169169+ duration_ms REAL,
170170+171171+ -- Session metadata
172172+ user_id TEXT,
173173+ tenant_id TEXT,
174174+ client_ip TEXT,
175175+ user_agent TEXT,
176176+177177+ -- Session metrics
178178+ log_count INTEGER DEFAULT 0,
179179+ error_count INTEGER DEFAULT 0,
180180+ warning_count INTEGER DEFAULT 0,
181181+182182+ -- Performance metrics
183183+ total_duration_ms REAL,
184184+ total_memory_bytes INTEGER,
185185+186186+ created_at REAL DEFAULT (julianday('now'))
187187+);
188188+189189+-- System metrics snapshot table
190190+CREATE TABLE IF NOT EXISTS system_metrics (
191191+ timestamp REAL PRIMARY KEY,
192192+193193+ -- CPU metrics
194194+ cpu_usage_percent REAL,
195195+ cpu_user_percent REAL,
196196+ cpu_system_percent REAL,
197197+ cpu_idle_percent REAL,
198198+ load_avg_1m REAL,
199199+ load_avg_5m REAL,
200200+ load_avg_15m REAL,
201201+202202+ -- Memory metrics
203203+ memory_total_bytes INTEGER,
204204+ memory_used_bytes INTEGER,
205205+ memory_free_bytes INTEGER,
206206+ memory_available_bytes INTEGER,
207207+ swap_used_bytes INTEGER,
208208+ swap_free_bytes INTEGER,
209209+210210+ -- Disk metrics
211211+ disk_read_bytes_per_sec REAL,
212212+ disk_write_bytes_per_sec REAL,
213213+ disk_usage_percent REAL,
214214+215215+ -- Network metrics
216216+ network_rx_bytes_per_sec REAL,
217217+ network_tx_bytes_per_sec REAL,
218218+ network_connections INTEGER,
219219+220220+ -- Process metrics
221221+ process_count INTEGER,
222222+ thread_count INTEGER,
223223+ fiber_count INTEGER,
224224+225225+ -- GC metrics (OCaml specific)
226226+ gc_minor_collections INTEGER,
227227+ gc_major_collections INTEGER,
228228+ gc_heap_words INTEGER,
229229+ gc_live_words INTEGER,
230230+231231+ created_at REAL DEFAULT (julianday('now'))
232232+);
233233+234234+-- Comprehensive indexes for efficient querying
235235+CREATE INDEX IF NOT EXISTS idx_logs_timestamp ON logs(timestamp DESC);
236236+CREATE INDEX IF NOT EXISTS idx_logs_level_timestamp ON logs(level, timestamp DESC);
237237+CREATE INDEX IF NOT EXISTS idx_logs_source_timestamp ON logs(source, timestamp DESC);
238238+CREATE INDEX IF NOT EXISTS idx_logs_error_hash ON logs(error_hash) WHERE error_hash IS NOT NULL;
239239+CREATE INDEX IF NOT EXISTS idx_logs_session_id ON logs(session_id) WHERE session_id IS NOT NULL;
240240+CREATE INDEX IF NOT EXISTS idx_logs_request_id ON logs(request_id) WHERE request_id IS NOT NULL;
241241+CREATE INDEX IF NOT EXISTS idx_logs_trace_id ON logs(trace_id) WHERE trace_id IS NOT NULL;
242242+CREATE INDEX IF NOT EXISTS idx_logs_user_id ON logs(user_id) WHERE user_id IS NOT NULL;
243243+CREATE INDEX IF NOT EXISTS idx_logs_error_type ON logs(error_type) WHERE error_type IS NOT NULL;
244244+CREATE INDEX IF NOT EXISTS idx_logs_duration ON logs(duration_ms) WHERE duration_ms IS NOT NULL;
245245+CREATE INDEX IF NOT EXISTS idx_logs_status_code ON logs(status_code) WHERE status_code IS NOT NULL;
246246+247247+CREATE INDEX IF NOT EXISTS idx_patterns_last_seen ON patterns(last_seen DESC);
248248+CREATE INDEX IF NOT EXISTS idx_patterns_severity ON patterns(severity_score DESC) WHERE severity_score IS NOT NULL;
249249+CREATE INDEX IF NOT EXISTS idx_patterns_count ON patterns(occurrence_count DESC);
250250+CREATE INDEX IF NOT EXISTS idx_pattern_metrics_timestamp ON pattern_metrics(timestamp DESC);
251251+252252+-- Triggers to maintain FTS and update timestamps
253253+CREATE TRIGGER IF NOT EXISTS logs_fts_insert AFTER INSERT ON logs
254254+BEGIN
255255+ INSERT INTO logs_fts(rowid, message, error_type, error_code, source,
256256+ file_path, function_name, module_path, path, method,
257257+ stack_trace, tags, labels, context, custom_fields)
258258+ VALUES (new.id, new.message, new.error_type, new.error_code, new.source,
259259+ new.file_path, new.function_name, new.module_path, new.path, new.method,
260260+ new.stack_trace, new.tags, new.labels, new.context, new.custom_fields);
261261+262262+ UPDATE logs SET indexed_at = julianday('now') WHERE id = new.id;
263263+END;
264264+265265+CREATE TRIGGER IF NOT EXISTS patterns_update_timestamp AFTER UPDATE ON patterns
266266+BEGIN
267267+ UPDATE patterns SET updated_at = julianday('now') WHERE id = new.id;
268268+END;
269269+270270+-- Views for common queries
271271+CREATE VIEW IF NOT EXISTS recent_errors AS
272272+SELECT
273273+ error_hash,
274274+ error_type,
275275+ error_code,
276276+ COUNT(*) as count,
277277+ COUNT(DISTINCT session_id) as affected_sessions,
278278+ COUNT(DISTINCT user_id) as affected_users,
279279+ MAX(timestamp) as last_seen,
280280+ MIN(timestamp) as first_seen,
281281+ GROUP_CONCAT(DISTINCT source) as sources,
282282+ AVG(duration_ms) as avg_duration_ms,
283283+ message as sample_message
284284+FROM logs
285285+WHERE level <= 2 -- Error and Warning
286286+ AND timestamp > julianday('now') - 1 -- Last 24 hours
287287+GROUP BY error_hash
288288+ORDER BY count DESC;
289289+290290+CREATE VIEW IF NOT EXISTS error_trends AS
291291+SELECT
292292+ date(timestamp) as day,
293293+ level,
294294+ COUNT(*) as count,
295295+ COUNT(DISTINCT error_hash) as unique_errors,
296296+ COUNT(DISTINCT session_id) as affected_sessions,
297297+ AVG(duration_ms) as avg_duration_ms
298298+FROM logs
299299+WHERE level <= 2
300300+GROUP BY date(timestamp), level
301301+ORDER BY day DESC, level;
302302+303303+CREATE VIEW IF NOT EXISTS slow_operations AS
304304+SELECT
305305+ source,
306306+ function_name,
307307+ COUNT(*) as count,
308308+ AVG(duration_ms) as avg_duration_ms,
309309+ MAX(duration_ms) as max_duration_ms,
310310+ MIN(duration_ms) as min_duration_ms,
311311+ SUM(duration_ms) as total_duration_ms
312312+FROM logs
313313+WHERE duration_ms IS NOT NULL
314314+GROUP BY source, function_name
315315+HAVING avg_duration_ms > 100 -- Operations slower than 100ms
316316+ORDER BY avg_duration_ms DESC;