Hadrian is experimental alpha software. Do not use in production.
Hadrian
Configuration

Observability Configuration

Logging, tracing, metrics, and monitoring configuration

The [observability] section configures logging, distributed tracing, Prometheus metrics, request logging, usage tracking, and response validation.

Overview

SubsectionPurpose
loggingConsole log format, level, and SIEM integration
tracingOpenTelemetry distributed tracing with OTLP export
metricsPrometheus metrics endpoint and histogram buckets
request_loggingRequest/response body logging with redaction
usageUsage data export to database and OTLP
dead_letter_queueFailed operations recovery and retry
response_validationOpenAI schema validation for responses

Logging

Configure console log output format and level.

[observability.logging]
level = "info"
format = "compact"
timestamps = true
file_line = false
include_spans = true
filter = "tower_http=debug,sqlx=warn"
SettingTypeDefaultDescription
levelstringinfoLog level: trace, debug, info, warn, error.
formatstringcompactOutput format (see below).
timestampsbooleantrueInclude timestamps in log output.
file_linebooleanfalseInclude file and line number in log output.
include_spansbooleantrueInclude tracing span information (JSON format only).
filterstringNoneAdditional filter directives (e.g., tower_http=debug).

Log Formats

FormatDescriptionUse Case
prettyHuman-readable multi-line format with colorsLocal development
compactSingle-line format with colorsDevelopment, simple deployments
jsonStructured JSON for log aggregationProduction, log pipelines
cefCommon Event Format for ArcSight, SplunkEnterprise SIEM integration
leefLog Event Extended Format for IBM QRadarIBM QRadar SIEM
syslogRFC 5424 Syslog formatStandard syslog servers

Environment Variable Override

The RUST_LOG environment variable takes precedence over config file settings:

RUST_LOG=debug ./hadrian
RUST_LOG=hadrian=debug,tower_http=trace ./hadrian

SIEM Configuration

For CEF, LEEF, and Syslog formats, configure additional SIEM-specific fields:

[observability.logging]
format = "cef"

[observability.logging.siem]
device_vendor = "Hadrian"
device_product = "Gateway"
device_version = "1.0.0"
hostname = "gateway-prod-01"
app_name = "hadrian"
facility = "local0"
leef_version = "2.0"
SettingTypeDefaultDescription
device_vendorstringHadrianVendor name for CEF/LEEF headers.
device_productstringGatewayProduct name for CEF/LEEF headers.
device_versionstringCrate versionVersion for CEF/LEEF headers.
hostnamestringSystem hostnameOverride hostname in log headers.
app_namestringhadrianApplication name for Syslog APP-NAME field.
facilitystringlocal0Syslog facility (see below).
leef_versionstring2.0LEEF format version (1.0 or 2.0).

Syslog Facilities

FacilityCodeDescription
kern0Kernel messages
user1User-level messages
daemon3System daemons
auth4Security/authorization
local016Local use 0 (default)
local1-local717-23Local use 1-7

Distributed Tracing

OpenTelemetry distributed tracing with OTLP export for request correlation across services.

[observability.tracing]
enabled = true
service_name = "hadrian"
service_version = "1.0.0"
environment = "production"

[observability.tracing.otlp]
endpoint = "http://jaeger:4317"
protocol = "grpc"
timeout_secs = 10
compression = true

[observability.tracing.otlp.headers]
Authorization = "Bearer ${OTLP_TOKEN}"

[observability.tracing.sampling]
strategy = "ratio"
rate = 0.1

[observability.tracing.resource_attributes]
"deployment.region" = "us-east-1"
"k8s.namespace" = "ai-gateway"

Tracing Configuration

SettingTypeDefaultDescription
enabledbooleanfalseEnable OpenTelemetry tracing.
service_namestringai-gatewayService name in traces.
service_versionstringNoneService version in traces.
environmentstringNoneDeployment environment (e.g., production).
propagationstringtrace_contextContext propagation format.
resource_attributesmap{}Additional resource attributes for all spans.

OTLP Exporter

SettingTypeDefaultDescription
endpointstringOTLP collector endpoint URL.
protocolstringgrpcProtocol: grpc or http.
timeout_secsinteger10Export timeout in seconds.
compressionbooleantrueEnable gzip compression.
headersmap{}Headers for authentication.

Sampling Strategies

StrategyDescription
always_onSample all traces (default).
always_offSample no traces.
ratioSample a percentage of traces (use rate field).
parent_basedInherit sampling decision from parent span.

Propagation Formats

FormatDescription
trace_contextW3C Trace Context (default, recommended)
b3Zipkin B3 format
jaegerJaeger native format
multiTraceContext + Baggage combined

Prometheus Metrics

Expose Prometheus metrics for monitoring dashboards and alerting.

[observability.metrics]
enabled = true
latency_buckets_ms = [10, 50, 100, 250, 500, 1000, 2500, 5000, 10000]
token_buckets = [10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000]

[observability.metrics.prometheus]
enabled = true
path = "/metrics"
process_metrics = true
SettingTypeDefaultDescription
enabledbooleantrueEnable metrics collection.
latency_buckets_msfloat[][10, 50, 100, 250, 500, 1000, 2500, 5000, 10000]Histogram buckets for latency (ms).
token_bucketsfloat[][10, 50, 100, 500, 1000, 5000, 10000, 50000, 100000]Histogram buckets for token counts.

Prometheus Endpoint

SettingTypeDefaultDescription
enabledbooleantrueEnable the /metrics endpoint.
pathstring/metricsPath for the Prometheus scrape endpoint.
process_metricsbooleantrueInclude process metrics (memory, CPU).

Available Metrics

HTTP Metrics

MetricTypeLabelsDescription
http_requests_totalCountermethod, path, status, status_classTotal HTTP requests.
http_request_duration_secondsHistogrammethod, path, status_classRequest latency.
active_connectionsGaugeCurrent active connections.

LLM Metrics

MetricTypeLabelsDescription
llm_requests_totalCounterprovider, model, statusTotal LLM requests.
llm_request_duration_secondsHistogramprovider, modelLLM request latency.
llm_input_tokens_totalCounterprovider, modelTotal input tokens processed.
llm_output_tokens_totalCounterprovider, modelTotal output tokens generated.
llm_input_tokensHistogramprovider, modelInput tokens per request.
llm_output_tokensHistogramprovider, modelOutput tokens per request.
llm_cost_microcents_totalCounterprovider, modelTotal cost in microcents.

Streaming Metrics

MetricTypeLabelsDescription
llm_streaming_chunks_totalCounterprovider, modelTotal streaming chunks.
llm_streaming_chunk_countHistogramprovider, modelChunks per stream.
llm_streaming_time_to_first_chunk_secondsHistogramprovider, modelTime to first chunk (TTFC).
llm_streaming_duration_secondsHistogramprovider, modelTotal stream duration.
llm_streaming_completions_totalCounterprovider, model, outcomeStream completions by outcome.

Authentication & Authorization

MetricTypeLabelsDescription
auth_attempts_totalCountermethod, statusAuthentication attempts.
budget_checks_totalCounterresultBudget check results.
budget_warnings_totalCounterperiodBudget warning triggers.
budget_spend_percentageGaugeapi_key_id, periodCurrent spend percentage.
rate_limit_checks_totalCounterresultRate limit check results.

Provider Health

MetricTypeLabelsDescription
provider_healthGaugeproviderProvider health (1=healthy, 0=unhealthy).
provider_health_checks_totalCounterprovider, statusHealth check results.
provider_health_check_duration_secondsHistogramproviderHealth check latency.
provider_circuit_breaker_stateGaugeproviderCircuit breaker state (0=closed, 1=open, 2=half_open).
provider_circuit_breaker_failure_countGaugeproviderCurrent failure count.
provider_fallback_attempts_totalCounterfrom_provider, to_provider, successFallback attempts.
provider_fallback_exhausted_totalCounterprimary_provider, chain_lengthExhausted fallback chains.

RAG / Knowledge Base Metrics

MetricTypeLabelsDescription
rag_document_processing_totalCounterstatus, file_typeDocuments processed.
rag_document_processing_duration_secondsHistogramstatus, file_typeProcessing time.
rag_document_chunks_totalCounterfile_typeTotal chunks created.
rag_embedding_requests_totalCounterprovider, model, statusEmbedding API calls.
rag_embedding_duration_secondsHistogramprovider, modelEmbedding latency.
rag_file_search_totalCounterstatus, cacheFile search queries.
rag_file_search_duration_secondsHistogramstatus, cacheSearch latency.
rag_vector_store_operations_totalCounterbackend, operation, statusVector DB operations.

Guardrails Metrics

MetricTypeLabelsDescription
guardrails_evaluations_totalCounterprovider, stage, resultGuardrails evaluations.
guardrails_latency_secondsHistogramprovider, stageEvaluation latency.
guardrails_violations_totalCounterprovider, category, severity, actionViolations detected.
guardrails_timeouts_totalCounterprovider, stageEvaluation timeouts.
guardrails_errors_totalCounterprovider, stage, error_typeProvider errors.

System Metrics

MetricTypeLabelsDescription
gateway_errors_totalCountererror_type, error_code, providerGateway errors.
cache_operations_totalCountercache_type, operation, resultCache operations.
db_operations_totalCounteroperation, table, statusDatabase operations.
db_operation_duration_secondsHistogramoperation, tableDatabase operation latency.
dlq_operations_totalCounteroperation, entry_typeDead letter queue operations.
retention_deletions_totalCountertableRecords deleted by retention.

Request Logging

Log request and response bodies for debugging and auditing.

Request logging can expose sensitive data. Enable only in controlled environments and always use redact_sensitive = true in production.

[observability.request_logging]
enabled = true
log_request_body = true
log_response_body = false
max_body_size = 10240
redact_sensitive = true
redact_fields = ["api_key", "password", "secret", "authorization"]
SettingTypeDefaultDescription
enabledbooleanfalseEnable request logging.
log_request_bodybooleanfalseLog request bodies.
log_response_bodybooleanfalseLog response bodies.
max_body_sizeinteger10240Maximum body size to log (bytes).
redact_sensitivebooleantrueRedact sensitive fields.
redact_fieldsstring[]["api_key", "password", "secret", "authorization"]Fields to redact.

Log Destinations

[observability.request_logging]
enabled = true

# Log to a separate file
[observability.request_logging.destination]
type = "file"
path = "/var/log/hadrian/requests.log"

[observability.request_logging.destination.rotation]
type = "daily"
DestinationConfiguration
stdoutLog to standard output (same as regular logs).
fileLog to a file with optional rotation (daily, hourly, size).
httpPOST logs to an HTTP endpoint with custom headers.

Usage Tracking

Configure where API usage data (tokens, costs, latency) is recorded.

[observability.usage]
database = true

[observability.usage.buffer]
max_size = 1000
flush_interval_ms = 1000
max_pending_entries = 10000
SettingTypeDefaultDescription
databasebooleantrueWrite usage records to the database.

Buffer Configuration

Usage records are buffered before writing to improve performance.

SettingTypeDefaultDescription
max_sizeinteger1000Flush buffer when this many records accumulate.
flush_interval_msinteger1000Flush buffer at this interval (milliseconds).
max_pending_entriesinteger10000Drop oldest entries if pending exceeds this limit.

OTLP Usage Export

Export usage records to an OpenTelemetry-compatible backend:

[observability.usage.otlp]
enabled = true
endpoint = "http://otel-collector:4317"
protocol = "grpc"
timeout_secs = 10
compression = true
service_name = "hadrian-usage"

[observability.usage.otlp.headers]
Authorization = "Bearer ${OTLP_TOKEN}"

OTLP Usage Attributes

Each exported usage record includes the following OpenTelemetry attributes for attribution and filtering:

AttributeDescription
hadrian.request_idUnique request identifier
hadrian.modelModel used (e.g., gpt-4o)
hadrian.providerProvider name (e.g., openai)
hadrian.api_key_idAPI key used (if applicable)
hadrian.user_idAuthenticated user ID (session or user-owned key)
hadrian.org_idOrganization context
hadrian.project_idProject context (from key or X-Hadrian-Project)
hadrian.team_idTeam context (from team-scoped key)
hadrian.service_account_idService account that owns the API key
hadrian.input_tokensInput token count
hadrian.output_tokensOutput token count
hadrian.cost_microcentsCalculated cost in microcents

These attributes enable building Grafana dashboards, alerts, and queries filtered by organization, team, project, or individual user.

Dead Letter Queue

Capture failed operations (usage logging, etc.) for later retry.

[observability.dead_letter_queue]
type = "redis"
url = "${REDIS_URL}"
key_prefix = "gw:dlq:"
max_entries = 100000
ttl_secs = 604800  # 7 days

[observability.dead_letter_queue.retry]
enabled = true
interval_secs = 60
initial_delay_secs = 60
max_delay_secs = 3600
backoff_multiplier = 2.0
max_retries = 10
batch_size = 100
prune_enabled = true

DLQ Types

TypeConfigurationUse Case
filepath, max_file_size_mb, max_filesSingle-node, local storage
redisurl, key_prefix, max_entries, ttl_secsMulti-node, shared storage
databasetable_name, max_entries, ttl_secsUses existing database

Retry Configuration

SettingTypeDefaultDescription
enabledbooleantrueEnable automatic retry processing.
interval_secsinteger60Interval between retry runs (seconds).
initial_delay_secsinteger60Initial delay before first retry.
max_delay_secsinteger3600Maximum delay between retries.
backoff_multiplierfloat2.0Exponential backoff multiplier.
max_retriesinteger10Maximum retry attempts before giving up.
batch_sizeinteger100Records to process per retry run.
prune_enabledbooleantrueAutomatically delete expired entries.

Response Validation

Validate API responses against the OpenAI OpenAPI specification.

[observability.response_validation]
enabled = true
mode = "warn"
SettingTypeDefaultDescription
enabledbooleanfalseEnable response schema validation.
modestringwarnwarn (log and continue) or error (return 500).

Response validation helps catch format issues from non-OpenAI providers. Use warn mode in production to log issues without breaking requests. Use error mode during provider integration testing.

Complete Examples

Development

[observability.logging]
level = "debug"
format = "pretty"

[observability.metrics]
enabled = true

[observability.metrics.prometheus]
enabled = true
path = "/metrics"

Production with Jaeger

[observability.logging]
level = "info"
format = "json"

[observability.tracing]
enabled = true
service_name = "hadrian"
service_version = "1.0.0"
environment = "production"

[observability.tracing.otlp]
endpoint = "http://jaeger:4317"
protocol = "grpc"
compression = true

[observability.tracing.sampling]
strategy = "ratio"
rate = 0.1

[observability.metrics]
enabled = true

[observability.metrics.prometheus]
enabled = true
path = "/metrics"

[observability.usage]
database = true

[observability.usage.buffer]
max_size = 1000
flush_interval_ms = 1000

[observability.dead_letter_queue]
type = "redis"
url = "${REDIS_URL}"
ttl_secs = 604800

Enterprise SIEM Integration

[observability.logging]
level = "info"
format = "cef"

[observability.logging.siem]
device_vendor = "Acme Corp"
device_product = "AI Gateway"
device_version = "1.0.0"
hostname = "gateway-prod-01"
facility = "local0"

[observability.tracing]
enabled = true
service_name = "ai-gateway"

[observability.tracing.otlp]
endpoint = "https://otel.internal:4317"
protocol = "grpc"

[observability.tracing.otlp.headers]
Authorization = "Bearer ${OTEL_TOKEN}"

[observability.metrics]
enabled = true

[observability.request_logging]
enabled = true
log_request_body = true
log_response_body = true
redact_sensitive = true

[observability.request_logging.destination]
type = "file"
path = "/var/log/hadrian/requests.log"

[observability.request_logging.destination.rotation]
type = "daily"

Grafana Cloud

[observability.logging]
level = "info"
format = "json"

[observability.tracing]
enabled = true
service_name = "hadrian"
environment = "production"

[observability.tracing.otlp]
endpoint = "https://otlp-gateway-prod-us-central-0.grafana.net/otlp"
protocol = "http"

[observability.tracing.otlp.headers]
Authorization = "Basic ${GRAFANA_OTLP_TOKEN}"

[observability.tracing.sampling]
strategy = "ratio"
rate = 0.05

[observability.usage.otlp]
enabled = true
endpoint = "https://otlp-gateway-prod-us-central-0.grafana.net/otlp"
protocol = "http"

[observability.usage.otlp.headers]
Authorization = "Basic ${GRAFANA_OTLP_TOKEN}"

On this page