Structured Logging¶
Hubuum writes newline-delimited JSON logs only. JSON is the stable operational interface for containers, collectors, and command-line tooling; there is no text formatter toggle. Configure verbosity with HUBUUM_LOG_LEVEL.
Configuration¶
| Variable | Default | Description |
|---|---|---|
HUBUUM_LOG_LEVEL |
info |
Minimum log level: trace, debug, info, warn, or error |
Common Fields¶
Every log record includes:
| Field | Description |
|---|---|
time |
UTC timestamp in RFC 3339 format with millisecond precision |
severity |
Log level as TRACE, DEBUG, INFO, WARN, or ERROR |
message |
Stable event message |
Request-scoped records also include request_id and, when accepted from the client, correlation_id. Authenticated requests record principal_id on the request span after bearer token resolution. When an OpenTelemetry span is active, records also include fixed-width lowercase trace_id and span_id fields. See Distributed Tracing for export and propagation policy.
The server emits one server startup record at INFO after binding succeeds. It includes the package version, build Git SHA, bind address, TLS state, worker counts, storage and authorization backends, log format and level, and the number of enabled event sinks. Release and container builds populate git_sha; local builds report unknown unless HUBUUM_BUILD_GIT_SHA is set while compiling.
db_backend remains as a compatibility alias for storage_backend while the
only selectable implementation is PostgreSQL.
Request Logs¶
Request completion is the canonical HTTP request log event. Actix's default text request logger is disabled to avoid duplicate unstructured logs.
Completion records include:
| Field | Description |
|---|---|
message |
request complete |
method |
HTTP method |
path |
Request path without query string |
status |
HTTP response status |
client_ip |
Resolved client IP when available |
elapsed_ms |
Request duration in whole milliseconds |
error |
Present when a downstream service error ended the request |
Severity is derived from the outcome:
| Outcome | Severity |
|---|---|
Successful /healthz and /readyz probes |
DEBUG |
2xx and 3xx |
INFO |
4xx |
WARN |
5xx |
ERROR |
Hubuum applies the status-to-severity mapping to downstream service errors as well as normal responses. Successful liveness and readiness probe completions use DEBUG to avoid flooding normal operational logs; failed probes retain their status-derived severity. Early middleware rejections, including client-allowlist denials, are returned as responses so they receive the same completion event and x-request-id header as handler responses.
Clients may send X-Correlation-ID. Accepted values are 1 to 128 visible ASCII bytes without whitespace. Hubuum echoes accepted values as x-correlation-id; invalid values are ignored without logging or echoing the supplied value. Hubuum always returns x-request-id.
Operation And Authorization Logs¶
Domain mutation logs are queued by the audit event writer and emitted at INFO only after the surrounding database transaction commits. Failed and rolled-back transactions discard their queued mutation logs. These logs use the audit catalog labels:
| Field | Description |
|---|---|
operation |
mutation_committed |
mutation_phase |
committed |
entity_type |
Catalog entity label, such as collection |
action |
Catalog action label, such as created |
entity_id |
Entity identifier when available |
actor_principal_id |
Acting principal when available |
Service list/get paths log at DEBUG. The audit-event query path additionally uses the standardized operation=read helper with optional catalog entity, action, and entity ID filters.
Authorization decision logs use:
| Decision | Severity |
|---|---|
| Grant | DEBUG |
| Denial | WARN |
Authorization records include event_type=authorization, decision, principal_id, requested permissions as a JSON array, derived action and entity_type when the requested permissions share them, nullable collection_id and collection_count, and a short reason.
Storage Diagnostics¶
Logical storage calls run inside a storage_operation debug span with the
bounded fields backend, capability, and operation. Successful calls emit
storage operation complete at DEBUG. Expected domain outcomes such as not
found, conflict, validation, and stale preconditions emit
storage operation rejected at DEBUG. Database, unavailable, and internal
failures emit storage operation failed at WARN.
PostgreSQL pool checkout and helper boundaries use the corresponding
storage backend connection acquired, storage backend operation complete,
and failure events. These include the bounded caller and operation fields,
plus elapsed milliseconds. They do not include SQL text or arguments.
Use the lifecycle events to debug application use cases and the PostgreSQL events to debug connection or transaction behavior. A lifecycle call may contain more than one implementation-level operation.
Sensitive Data Rules¶
Do not log secrets or high-volume payloads. In particular, logs must not include bearer tokens or token fragments, token hashes, password hashes, sink secrets, raw Authorization headers, request bodies, response bodies, audit before or after snapshots, or remote target secret material.
Prefer stable identifiers, catalog labels, counts, and short reason strings over raw payload data.
jq Recipes¶
Pretty-print logs:
Show failed requests:
Trace one request:
Trace a client-supplied correlation ID:
Find all local records for an OpenTelemetry trace:
List authorization denials:
Operator monitoring¶
Use the shared operator package for Grafana dashboards, Prometheus recording and alerting rules, SLO definitions and response runbooks. The same assets work with the optional single-host stack, independently managed Prometheus/Grafana installations, and Prometheus Operator. Pin the package to your server release and scrape every process directly with deployment labels.