Developer guide: writing logs#

This guide provides language-specific setup instructions and standards for initializing loggers and emitting diagnostic logs when developing or modifying CLP components.

Note

Always prefer UTC service timestamps. Time zone conversions should be handled downstream in log viewers or aggregation systems.

Python#

Python orchestration services should use structlog for structured JSON logging and bind context variables where appropriate.

from clp_py_utils.clp_logging import get_structlog_logger

log = get_structlog_logger("service_name")
log.info("hello, %s!", "world")

Note

Existing Python services use stdlib loggers whose handlers are configured with structlog’s ProcessorFormatter. Follow the established convention when modifying those services.

Rust#

Rust HTTP services should initialize tracing at process startup using clp_rust_utils::logging::set_up_logging and keep the returned guard alive for the lifetime of the process:

let _guard = clp_rust_utils::logging::set_up_logging("service_name.log");

// Choose structured logging over formatting values directly into the message field.
tracing::info!(job_id = compression_job_id, "Compression job completed.");

WebUI#

WebUI server code should use Fastify’s Pino logger. Use request.log for request-scoped logs and app.log for startup, shutdown, and application-level logs:

// Request-scoped
request.log.info({searchJobId}, "Search submitted");
request.log.error(err, "Failed to submit search");

// Application-scoped
app.log.info("WebUI server listening on port 3000");

WebUI client code should use console.* for browser diagnostics:

console.error("Failed to submit query:", err);

Core and setup tools#

  • Native core binaries (clp, clp-s, glt, native reducer_server) should continue using spdlog and the spdlog initialization already defined in each binary’s startup code.

  • Package/setup tools (DB initialization scripts, package controllers) should use the standard Python logger.