Skip to content

Instantly share code, notes, and snippets.

@intellectronica
Created September 6, 2025 21:40
Show Gist options
  • Save intellectronica/b264f5ccb1ba319bb465af8531d99249 to your computer and use it in GitHub Desktop.
Save intellectronica/b264f5ccb1ba319bb465af8531d99249 to your computer and use it in GitHub Desktop.
Recipe: Submit NGINX logs to Logfire via OTEL
# --- OTel + log file prep (before nginx starts) ---
# Ensure /var/log/nginx exists
mkdir -p /var/log/nginx
# Replace default Docker symlinks (to stdout/stderr) with real files so the collector can tail them
for f in access.log error.log; do
if [ -L "/var/log/nginx/$f" ]; then
mv -f "/var/log/nginx/$f" "/var/log/nginx/$f.dockerlink" || true
fi
: > "/var/log/nginx/$f"
chown nginx:nginx "/var/log/nginx/$f" 2>/dev/null || true
done
# Start the OpenTelemetry Collector in the background (token provided via env)
otelcol-contrib --config /etc/otelcol/config.yaml &
# --- end OTel setup ---
# ...
# --- Logfire JSON access logs + error logs to files ---
log_format logfire_json escape=json
'{ "ts":"$time_iso8601", "remote_ip":"$remote_addr", "method":"$request_method",'
' "uri":"$request_uri", "protocol":"$server_protocol", "host":"$host",'
' "status":$status, "bytes_sent":$bytes_sent, "referer":"$http_referer",'
' "user_agent":"$http_user_agent", "request_time":$request_time, '
' "upstream_addr":"$upstream_addr", "upstream_status":"$upstream_status",'
' "upstream_response_time":"$upstream_response_time" }';
access_log /var/log/nginx/access.log logfire_json;
error_log /var/log/nginx/error.log warn;
# --- end logging config ---
# ...
receivers:
filelog/access:
include: [ /var/log/nginx/access.log ]
start_at: end
include_file_path: true
operators:
- type: json_parser
parse_from: body
parse_to: attributes
on_error: drop
- type: time_parser
parse_from: attributes.ts
layout_type: gotime
layout: 2006-01-02T15:04:05Z07:00
on_error: drop
- type: add
field: attributes.log.type
value: nginx_access
filelog/error:
include: [ /var/log/nginx/error.log ]
start_at: end
include_file_path: true
operators:
- type: regex_parser
regex: '^(?P<ts>\\d{4}/\\d{2}/\\d{2} \\d{2}:\\d{2}:\\d{2}) \\[(?P<severity>\\w+)\\]'
on_error: drop
- type: time_parser
parse_from: attributes.ts
layout_type: gotime
layout: 2006/01/02 15:04:05
on_error: drop
- type: add
field: attributes.log.type
value: nginx_error
processors:
resource:
attributes:
- key: service.name
value: nginx
action: upsert
batch: {}
exporters:
otlphttp/logfire:
logs_endpoint: https://logfire-us.pydantic.dev/v1/logs
headers:
Authorization: ${LOGFIRE_WRITE_TOKEN}
service:
telemetry:
logs:
level: warn
pipelines:
logs:
receivers: [filelog/access, filelog/error]
processors: [resource, batch]
exporters: [otlphttp/logfire]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment