Skip to main content

How to Configure Logging

Enable debug logging for troubleshooting, capture audit events, and scrape Prometheus metrics.

Versions

This page targets core engine 2.0.3 (the sochdb-grpc-server binary). SDK logging snippets use Python SDK 0.5.9 and Node.js SDK 0.5.3.


Problem​

You need to see what SochDB is doing internally for debugging, capture audit logs for compliance, or expose runtime metrics to Prometheus.


Solution​

1. RUST_LOG (the engine's only log filter)​

The sochdb-grpc-server binary uses tracing with an EnvFilter built from the RUST_LOG environment variable. There is no [logging] config-file section and no JSON/file/rotation options in the server today — RUST_LOG (plus the --debug flag below) is the control surface.

# Everything at debug
export RUST_LOG=debug

# Just the gRPC server crate at debug
export RUST_LOG=sochdb_grpc=debug

# A specific module only (note: Rust targets use underscores)
export RUST_LOG=sochdb_storage::wal=debug

# Mix per-crate levels
export RUST_LOG=info,sochdb_grpc=debug,sochdb_index::hnsw=trace

# Trace everything (very verbose)
export RUST_LOG=trace

Workspace crates you can target (directory names use hyphens, but RUST_LOG targets use underscores): sochdb_grpc, sochdb_kernel, sochdb_storage, sochdb_index, sochdb_query, sochdb_memory, sochdb_mcp.

note

RUST_LOG must be set before the process starts. If RUST_LOG is unset, the server falls back to a default level (see --debug below). The standard tracing_subscriber::EnvFilter syntax applies: target=level, comma-separated, with an optional bare default level.

2. The --debug flag​

The server exposes a single boolean flag that changes the default filter:

# Default filter becomes "info"
sochdb-grpc-server

# Default filter becomes "debug" (-d is the short form)
sochdb-grpc-server --debug
StateDefault filter (when RUST_LOG is unset)
no flaginfo
--debug / -ddebug
important

RUST_LOG always wins. If RUST_LOG is set, it overrides whatever --debug would have chosen. Use --debug for a quick bump and RUST_LOG for fine-grained, per-module control.

3. Audit logging​

Audit logging is on by default in the server's security layer (audit_enabled: true). Each entry is emitted through tracing under the audit target, so audit records show up in the same stdout/stderr stream as normal logs — there is no separate audit file in the default binary.

Entries are buffered and flushed every audit_flush_threshold (default 100) records. The AuditLogEntry JSON shape is fixed:

{"timestamp":1733911932,"principal_id":"app_service","tenant_id":"default","action":"kv_put","resource":"users","result":"success","request_id":"req-42","client_ip":"10.0.0.7"}

result is one of success, failure, or denied. To isolate audit records, filter on the target:

export RUST_LOG=info,audit=info
sochdb-grpc-server | grep '"action"'
Audit files are a library API, not a CLI flag

The AuditLogger::with_log_path(threshold, path) constructor can persist audit entries to a dedicated file, but the sochdb-grpc-server binary does not expose a CLI flag for it — it always uses the in-memory + tracing logger. There is also no configurable list of audited event types; the logger records whatever actions the security layer reports.

4. Prometheus metrics (/metrics on port 9090)​

The server runs a dedicated Prometheus HTTP endpoint on its own OS thread (sochdb-metrics-http), separate from the gRPC port.

# Default metrics port is 9090
sochdb-grpc-server

# Override the port
sochdb-grpc-server --metrics-port 9100

# Disable the metrics endpoint entirely
sochdb-grpc-server --metrics-port 0

Endpoints (bound to 0.0.0.0:<metrics-port>):

Method + PathPurpose
GET /metricsPrometheus text exposition (version=0.0.4)
GET /healthLiveness probe, returns 200 OK
anything else404
The metrics endpoint is not behind --auth

/metrics and /health are served by a plain HTTP listener with no authentication, intended for in-cluster scraping and probes. Keep the metrics port on a trusted network or behind your ingress.

Scrape config:

scrape_configs:
- job_name: sochdb
static_configs:
- targets: ["sochdb:9090"]

A representative sample of exported series (HNSW index metrics are auto-included via the default registry):

sochdb_grpc_requests_total{service,method}
sochdb_grpc_errors_total{service,method,code}
sochdb_grpc_request_duration_seconds
sochdb_grpc_active_connections
sochdb_sql_queries_total{statement_type}
sochdb_sql_query_duration_seconds
sochdb_transactions_total{outcome}
sochdb_tables_count
sochdb_storage_bytes
sochdb_wal_bytes
sochdb_wal_writes_total
sochdb_wal_fsync_total
sochdb_cache_operations_total{result}
sochdb_uptime_seconds
sochdb_build_info{version,rustc}

Use sochdb_build_info to confirm the running engine version (it carries a version label, e.g. 2.0.3).

5. SDK-side logging​

The language SDKs log through their host runtime's standard logging facilities — they do not read RUST_LOG.

import logging

# Turn on debug logging for the sochdb SDK logger
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("sochdb")
logger.setLevel(logging.DEBUG)

handler = logging.FileHandler("sochdb-client.log")
handler.setFormatter(logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
))
logger.addHandler(handler)

Example Output​

Default (info) startup​

2026-06-13T10:15:30.001Z  INFO sochdb_grpc::metrics_server: Prometheus metrics server listening on http://0.0.0.0:9090/metrics
2026-06-13T10:15:30.010Z INFO sochdb_grpc: Authentication disabled (use --auth to enable)
2026-06-13T10:15:30.011Z INFO sochdb_grpc: Starting SochDB gRPC server on 127.0.0.1:50051
2026-06-13T10:15:30.011Z INFO sochdb_grpc: Server version: 2.0.3

Debug (--debug or RUST_LOG=debug)​

2026-06-13T10:15:32.123Z DEBUG sochdb_storage::wal: Appending record: txn_id=42, size=1024
2026-06-13T10:15:32.124Z DEBUG sochdb_kernel: Snapshot created: ts=1000042
2026-06-13T10:15:32.125Z DEBUG sochdb_index::hnsw: Search: k=10, ef=500, candidates=127

Audit record (emitted on the audit target)​

{"timestamp":1733911932,"principal_id":"app_service","tenant_id":"default","action":"transaction_commit","resource":"orders","result":"success","request_id":"req-42","client_ip":null}

Discussion​

Log Levels​

LevelUse CasePerformance Impact
errorProduction (critical only)Minimal
warnProduction (with warnings)Minimal
infoProduction (recommended, the default)Low
debugDevelopment / troubleshootingModerate
traceDeep debugging onlyHigh

The sochdb-plugin-logging crate​

The workspace ships an example plugin, sochdb-plugin-logging (JsonLoggingPlugin), that implements the kernel's ObservabilityExtension trait and emits structured JSON logs, metrics, and spans. It demonstrates the plugin architecture and is registered programmatically:

use sochdb_kernel::PluginManager;
use sochdb_plugin_logging::JsonLoggingPlugin;
use std::sync::Arc;

let plugins = PluginManager::new();
let logging = JsonLoggingPlugin::new();
plugins.register_observability(Arc::new(logging))?;
note

sochdb-plugin-logging is an embedded-engine plugin, not part of the sochdb-grpc-server binary's request logging. The server itself logs via tracing (see above). The plugin is AGPL-3.0-or-later, like the rest of the core engine.

Performance Considerations​

  • Higher verbosity (debug/trace) adds overhead; scope it to specific modules with RUST_LOG=target=level rather than enabling globally.
  • Audit entries are batched (flush threshold 100) to keep the hot path cheap.
  • Scraping /metrics is cheap, but very high scrape frequencies still cost CPU to encode the registry — 10–15s intervals are typical.

Security Notes​

  • Audit logs include principal_id, tenant_id, and client_ip — treat them as sensitive and ship to a SIEM.
  • The /metrics and /health endpoints have no authentication; keep the metrics port off the public internet.
  • Avoid running with global trace in production — it can surface keys/values that appear in lower-level traces.

See Also​