Ship logs with Fluent Bit to UptimeEye

Fluent Bit is a small (few MB) agent that tails files, parses them and ships batches. Its http output with Format json_lines matches UptimeEye's JSON-lines endpoint one to one — no plugin needed.

Endpoint: https://logs.uptimeeye.com/v1/ingest/jsonline

1.Tail files on a host or VM

The record_modifier filter adds the fields you want to filter on. _msg_field=log tells UptimeEye which key holds the message; json_date_key _time puts the timestamp where UptimeEye expects it.

fluent-bit.conf
[SERVICE]
    Flush        2
    storage.path /var/lib/fluent-bit/buffer

[INPUT]
    Name              tail
    Path              /var/log/myapp/*.log
    Tag               myapp
    Refresh_Interval  5
    Skip_Long_Lines   On
    storage.type      filesystem

[FILTER]
    Name    record_modifier
    Match   *
    Record  service myapp
    Record  env prod
    Record  host ${HOSTNAME}

[OUTPUT]
    Name             http
    Match            *
    Host             logs.uptimeeye.com
    Port             443
    tls              On
    URI              /v1/ingest/jsonline?_msg_field=log&_stream_fields=service,env
    Format           json_lines
    json_date_key    _time
    json_date_format iso8601
    Header           Authorization Bearer ue_ingest_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    compress         gzip
    Retry_Limit      False

2.Application logs in JSON? Parse them

Add a parser so each JSON key becomes a field instead of one opaque log string.

fluent-bit.conf (addition)
[INPUT]
    Name    tail
    Path    /var/log/myapp/*.log
    Tag     myapp
    Parser  json

# parsers.conf
[PARSER]
    Name        json
    Format      json
    Time_Key    time
    Time_Format %Y-%m-%dT%H:%M:%S.%L%z
Note: With a JSON parser the message key is whatever your app uses — set _msg_field accordingly, e.g. _msg_field=message.

3.Kubernetes

With the official Helm chart, keep the kubernetes filter (it attaches namespace, pod and container) and point the output at UptimeEye.

values.yaml (fluent/fluent-bit chart)
config:
  outputs: |
    [OUTPUT]
        Name             http
        Match            kube.*
        Host             logs.uptimeeye.com
        Port             443
        tls              On
        URI              /v1/ingest/jsonline?_msg_field=log&_stream_fields=kubernetes.namespace_name,kubernetes.container_name
        Format           json_lines
        json_date_key    _time
        json_date_format iso8601
        Header           Authorization Bearer ue_ingest_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
        compress         gzip

4.Search

service:=myapp on a host, kubernetes.container_name:=api on Kubernetes. Nested keys arrive as dotted field names.

Fields you get

These show up in the fields panel and can be used in every filter:

  • service, env, host (from the filter)
  • kubernetes.namespace_name, kubernetes.pod_name, kubernetes.container_name on Kubernetes
  • parsed JSON keys

Tips

  • Retry_Limit False keeps retrying with the filesystem buffer, so a network blip does not lose lines.
  • Multiline stack traces: use the built-in multiline filter with multiline.parser java (or python, go) before the output.
  • Fluent Bit's Elasticsearch output works as well: Name es, Host logs.uptimeeye.com, Port 443, tls On, Path /v1/ingest/elasticsearch, HTTP_User key, HTTP_Passwd <ingest key>, Suppress_Type_Name On.

FAQ

Which output should I use, http or es?
http with json_lines is simpler and lets you pass ingest options in the URI. Use es only if you already have an Elasticsearch-shaped pipeline.
Where do I get the ingest key?
In the app under API Keys → New API Key → type “Log ingest”. The key starts with ue_ingest_ and is shown once. Management keys (ue_live_) are refused by the ingest endpoint.
How do I check that logs arrive?
Open Logs in the app, pick the 15m range and search for service:=<your service>. New lines are searchable within about a second; Live tail shows them with a ~6 s delay.