FaultPilot

Logs documentation

Ship logs to FaultPilot.

Connect Docker containers, Linux services, or application events with durable buffering and secure project-scoped ingestion keys.

Open Logs dashboard

Four steps to your first event

Most installations take less than ten minutes.

01

Create a source

Create one source for each application or environment.

Open log sources
02

Create an ingest key

Open the source, select Manage ingest keys, and copy the new key once.

03

Configure shipping

Choose your environment below and replace the key placeholder.

04

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.

1

Set the secret

Add FAULTPILOT_TOKEN to your deployment environment. Do not commit it to Git or bake it into an image.

.env
FAULTPILOT_TOKEN="paste_your_ingest_key_here"
2

Add Fluent Bit to Docker Compose

The application writes through Docker's Fluentd logging driver while Fluent Bit keeps a bounded disk buffer.

docker-compose.yml
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:
3

Add the shipper configuration

Keep Content-Type implicit: Format json already creates it and duplicate headers can be rejected.

fluent-bit.conf
[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 100M
transform.lua
function 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"] }
    }
end
4

Start and verify

Start the sidecar, inspect its output, then run the verification request below.

Terminal
docker compose up -d fluent-bit
docker compose logs -f fluent-bit
5

Send a verification event

Successful ingestion returns HTTP 202. Open the source's Live Tail and look for install-test.

Terminal
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.

StatusMeaningAction
202Batch acceptedCommit the buffered chunk
401Key missing, paused, deleted, or incorrectReplace the key; avoid an endless retry storm
413Batch exceeds 256 KiBReduce the batch size
429Rate or ingestion-period allowance reachedHonor Retry-After and inspect source usage
503Temporary storage or platform pressureKeep the local chunk and retry with backoff