Configuration: observability and logging
This page documents the observability configuration surface for Ferron, including access logs, log formatters, metrics, tracing, and OTLP export.
Directives
Access logging
Access logs are configured via log blocks inside host or global scopes:
example.com {
log "access" {
format "json"
fields "method" "path" "status" "duration_secs"
}
}| Nested directive | Arguments | Description | Default |
|---|---|---|---|
format | <string> | Log formatter to use. Available formatters depend on which observability modules are loaded. | none |
fields | <string>... | Field names to include in the log output. When omitted, all available fields are emitted. | all fields |
Access log fields
Each access log entry contains the following fields:
| Field | Placeholder | Description |
|---|---|---|
path | {path} | The request URI path (e.g. /index.html) |
path_and_query | {path_and_query} | The request URI with path and query |
method | {method} | The HTTP request method (e.g. GET, POST) |
version | {version} | The HTTP version (e.g. HTTP/1.1, HTTP/2.0) |
scheme | {scheme} | The request scheme (http or https) |
client_ip | {client_ip} | The client IP address |
client_port | {client_port} | The client port number |
client_ip_canonical | {client_ip_canonical} | The client IP in canonical form |
server_ip | {server_ip} | The server IP address |
server_port | {server_port} | The server port number |
server_ip_canonical | {server_ip_canonical} | The server IP in canonical form |
auth_user | {auth_user} | The authenticated username, or - if not authenticated |
status | {status_code} | The HTTP response status code |
content_length | {content_length} | The response content length, or - if not available |
duration_secs | (none) | Request processing duration in seconds |
timestamp | (none) | Request timestamp in CLF format |
header_<name> | {header:<name>} | Request header values (one field per header) |
Log formatters
json
The JSON formatter serializes each access log entry as a single-line JSON object. Provided by the observability-format-json module.
example.com {
log "access" {
format "json"
}
}Example output:
{"method":"GET","path":"/index.html","status":200,"duration_secs":0.012,"client_ip":"127.0.0.1","remote_ip":"127.0.0.1"}Use the fields directive to limit which fields appear in the JSON output. If fields is not specified, all available access log fields are emitted.
text
The text formatter generates each access log entry as a plain text string using a configurable pattern. Provided by the observability-format-text module.
By default, it uses the Combined Log Format (CLF), the same format used by Apache and Nginx.
Configuration example:
example.com {
log "access" {
format "text"
}
}Example output:
127.0.0.1 - frank [05/Apr/2026:14:32:01 +0200] "GET /index.html HTTP/1.1" 200 1234 "http://www.example.com/start.html" "Mozilla/5.0"Pattern syntax
The access_pattern directive supports the following tokens:
| Token | Description | Example |
|---|---|---|
%field_name | Access log field | %client_ip, %status, %method |
%{Header-Name}i | Request header | %{Referer}i, %{User-Agent}i |
%{format}t | Timestamp with custom format | %{%Y-%m-%d %H:%M:%S}t |
%t | Timestamp (uses timestamp_format or CLF default) | %t |
%% | Literal % character | %% |
| Other text | Passed through literally | ", “, - |
Request headers are available via the %{Header-Name}i syntax. The header name is case-insensitive and hyphens are converted to underscores internally.
Metrics
Ferron emits OpenTelemetry-style metrics through the observability event system. Each module documents its own metrics:
- Core HTTP server metrics — active requests, request duration, and request count. See HTTP host directives.
- Rate limiting metrics — allowed and rejected requests. See Rate limiting.
- Response control metrics — aborted connections, IP blocks, and status rule matches. See HTTP response control.
- Static file metrics — files served and bytes sent, with compression and cache hit attributes. See Static file serving.
- Rewrite metrics — applied rewrites and invalid rewrite errors. See URL rewriting.
- Proxy metrics — backend selection, health, connection pooling, and TLS failures. See Reverse proxying.
- Process metrics — CPU time, CPU utilization, and memory usage from
/proc/self/stat. See Process metrics below.
Process metrics
The observability-process-metrics module collects process-level metrics automatically when an observability backend is configured. It reads /proc/self/stat every 1 second.
Platform support: Linux only. On other platforms, the module is a no-op.
process.cpu.time(Counter) — total CPU seconds broken down by different states.- Attributes:
cpu.mode("user"or"system")
- Attributes:
process.cpu.utilization(Gauge) — CPU utilization since the last measurement.- Attributes:
cpu.mode("user"or"system")
- Attributes:
process.memory.usage(UpDownCounter) — the change in physical memory (RSS) since the last measurement.process.memory.virtual(UpDownCounter) — the change in committed virtual memory (VMS) since the last measurement.
Tracing
Each HTTP request generates a root trace span and multiple nested spans for pipeline execution:
Root request span
StartSpan("ferron.request_handler")— emitted when the request enters the handler.- Attributes:
http.request.method,url.path,url.scheme,server.address,server.port,client.address
- Attributes:
EndSpan("ferron.request_handler", error)— emitted when the request completes.- Attributes:
http.response.status_code,http.route(if applicable),error.type(if status >= 400)
- Attributes:
Pipeline execution span
ferron.pipeline.execute— wraps the entire pipeline execution, including all forward and inverse stages.
Per-stage spans
Each pipeline stage generates its own forward and inverse span, enabling flame graph analysis:
| Span name | Module | Description |
|---|---|---|
ferron.stage.rewrite | http-rewrite | URL rewrite stage |
ferron.stage.rate_limit | http-ratelimit | Rate limiting stage |
ferron.stage.headers | http-headers | Response header manipulation stage |
ferron.stage.reverse_proxy | http-proxy | Reverse proxy stage |
ferron.stage.static_file | http-static | Static file serving stage |
ferron.stage.http_response | http-response | Response control stage |
ferron.stage.<name>.inverse | (any) | Inverse (cleanup) operation for a stage |
Error pipeline span
ferron.pipeline.execute_error— wraps error pipeline execution when generating error responses.- Attributes:
http.response.status_code
- Attributes:
Trace events are consumed by observability backends that support tracing (e.g. OTLP). All spans from the same request share the same trace_id, enabling correlated queries.
Prometheus export
For Prometheus-specific metrics export, see Prometheus metrics.
OTLP export
For OpenTelemetry Protocol (OTLP) export configuration, see OTLP observability.
Notes and troubleshooting
- If log files are not being written, verify the file paths are accessible and the Ferron process has write permissions.
- For global observability configuration (
console_log,log,error_logshorthand directives), see Core directives. - For log format details, see the
jsonandtextformatter sections above.