Logs documentation
Ship logs to FaultPilot.
Connect Docker containers, Linux services, or application events with durable buffering and secure project-scoped ingestion keys.
Four steps to your first event
Most installations take less than ten minutes.
Create an ingest key
Open the source, select Manage ingest keys, and copy the new key once.
Configure shipping
Choose your environment below and replace the key placeholder.
Verify in Live Tail
Send the test event, then confirm it appears in your source.
Choose your environment
Fluent Bit is the supported production shipper because it buffers locally and recovers automatically after outages.
Set the secret
Add FAULTPILOT_TOKEN to your deployment environment. Do not commit it to Git or bake it into an image.
FAULTPILOT_TOKEN="paste_your_ingest_key_here"Add Fluent Bit to Docker Compose
The application writes through Docker's Fluentd logging driver while Fluent Bit keeps a bounded disk buffer.
services:
fluent-bit:
image: fluent/fluent-bit:3.2
restart: unless-stopped
environment:
FAULTPILOT_TOKEN: ${FAULTPILOT_TOKEN}
volumes:
- ./fluent-bit.conf:/fluent-bit/etc/fluent-bit.conf:ro
- ./transform.lua:/fluent-bit/etc/transform.lua:ro
- fluent-bit-buffer:/fluent-bit/storage
ports:
- "127.0.0.1:24224:24224"
web:
# Your existing application configuration goes here.
logging:
driver: fluentd
options:
fluentd-address: "127.0.0.1:24224"
tag: "web"
fluentd-async: "true"
volumes:
fluent-bit-buffer:Add the shipper configuration
Keep Content-Type implicit: Format json already creates it and duplicate headers can be rejected.
[SERVICE]
Flush 2
Log_Level info
storage.path /fluent-bit/storage
storage.sync normal
storage.backlog.mem_limit 5M
[INPUT]
Name forward
Listen 0.0.0.0
Port 24224
storage.type filesystem
Mem_Buf_Limit 5M
[FILTER]
Name lua
Match *
Script /fluent-bit/etc/transform.lua
Call transform_faultpilot
[OUTPUT]
Name http
Match *
Host faultpilot.com
Port 443
URI /api/v1/logs/ingest/
Format json
Header Authorization Bearer ${FAULTPILOT_TOKEN}
Tls On
Tls.verify On
Retry_Limit False
storage.total_limit_size 100Mfunction transform_faultpilot(tag, timestamp, record)
local message = record["log"] or record["container_log"] or record["MESSAGE"] or ""
message = tostring(message):gsub("^%s*(.-)%s*$", "%1")
local level = "info"
if message:match("ERROR") or message:match("CRITICAL") or message:match("Traceback") then
level = "error"
elseif message:match("WARNING") or message:match("WARN") then
level = "warning"
elseif message:match("DEBUG") then
level = "debug"
end
return 1, timestamp, {
service = tag or "unknown-service",
level = level,
message = message,
metadata = { source = "docker_fluentd", stream = record["source"] or record["stream"] }
}
endStart and verify
Start the sidecar, inspect its output, then run the verification request below.
docker compose up -d fluent-bit
docker compose logs -f fluent-bitSend a verification event
Successful ingestion returns HTTP 202. Open the source's Live Tail and look for install-test.
export FAULTPILOT_TOKEN="paste_your_ingest_key_here"
curl --fail-with-body \
-H "Authorization: Bearer $FAULTPILOT_TOKEN" \
-H "Content-Type: application/json" \
-d '[{"service":"install-test","level":"info","message":"FaultPilot shipper connected"}]' \
https://faultpilot.com/api/v1/logs/ingest/Response and recovery guide
Configure the shipper according to the response—not every error should retry forever.
| Status | Meaning | Action |
|---|---|---|
202 | Batch accepted | Commit the buffered chunk |
401 | Key missing, paused, deleted, or incorrect | Replace the key; avoid an endless retry storm |
413 | Batch exceeds 256 KiB | Reduce the batch size |
429 | Rate or ingestion-period allowance reached | Honor Retry-After and inspect source usage |
503 | Temporary storage or platform pressure | Keep the local chunk and retry with backoff |