Logs
Collect app logs with Fluent Bit, search them in the Log Browser and link them to endpoints.
What it is#
Your applications' own log lines, collected by Fluent Bit, stored by Pulsimo, and shown next to the endpoints, metrics and incidents they belong to. Use them to see why something failed, not only that it failed.
Where to find it#
- Logs in the sidebar: the Log Browser and Sources.
- Endpoint → Logs tab: that endpoint's lines.
- Incident → Logs tab: errors around the failure, saved with the incident.
1. Send logs to Pulsimo#
A complete worked example (a Docker host, from the Fluent Bit folder to incident evidence) is in Logs end to end.
Logs are pushed: Fluent Bit runs next to your applications, reads their logs, and sends
them to Pulsimo's ingest address (POST /api/v1/logs/ingest) with its http output.
Pulsimo never connects to Fluent Bit, so Fluent Bit opens no port. A log source is
just the token one Fluent Bit (or app) uses to push, with its own limits and redaction.
Logs → Sources → Add log source: name it (e.g. prod-docker-host-1), choose where the
logs are, then Create and show setup. The ingest token is shown once. The setup has
two views:
- New Fluent Bit: the files and commands for a fresh agent, token filled in.
- I already run Fluent Bit: only the
[OUTPUT]to add next to your existing outputs (Elasticsearch, Loki, …). Set itsMatchto the tags Pulsimo should get, restart Fluent Bit. - Another shipper: one more output for Promtail, Grafana Alloy, Vector, Filebeat, Logstash, the OpenTelemetry Collector or Fluentd. Pulsimo also accepts the Loki push, Elasticsearch bulk and OTLP/HTTP protocols, so these need no plugin; see Hosts and containers.
[OUTPUT]
Name http
Match kube.* # the tags to send
Host pulsimo.example.com
Port 443
URI /api/v1/logs/ingest
Format json_lines
Json_date_key date
Json_date_format iso8601
Header Authorization Bearer plog_…
Header_Tag X-Fluent-Tag # lets Pulsimo read pod/namespace/container from the tag
Compress gzip
tls On
Retry_Limit 10| Where the logs are | What Pulsimo generates |
|---|---|
| Docker host | fluent-bit.conf that tails /var/lib/docker/containers/*/*-json.log (the files Docker already writes), docker-meta.lua that adds the container name, Compose project and service, image and published ports, and a docker-compose.yml service for Fluent Bit. No changes to your containers. |
| Kubernetes | pulsimo-values.yaml for the fluent/fluent-bit Helm chart (DaemonSet). The chart already tails /var/log/containers/*.log with the Kubernetes filter; the values only add the output. With your own values file, add the output under config.outputs next to your outputs. |
| Server (VM) log files | fluent-bit.conf with a tail input per application, and the commands to install Fluent Bit as a system service (/etc/fluent-bit/fluent-bit.conf, systemctl enable --now fluent-bit). |
| Server (VM) systemd journal | Same, with the systemd input. |
| Anything else | A curl example: any tool that can POST JSON lines (gzip accepted). |
Fluent Bit keeps a position file (DB) per input, so a restart neither loses nor repeats lines,
and it retries when Pulsimo is unreachable.
The Sources table shows each source's status (Receiving, Quiet, Waiting for first lines, Paused), lines received and lines dropped over its limit. Token issues a new token (the old one stops at once); Setup shows the config again with the token masked.
What Pulsimo does to each line#
- Level: taken from
level/severityfields, else detected from the text (ERROR,WARN, panics, exceptions, HTTP 5xx in access logs). - Service: the first of: a
service/appfield; the pod labelapp.kubernetes.io/nameorapp; Composeproject-service; the container name (Docker or Kubernetes); the container in the Fluent Bit tag; the systemd unit; the tag's prefix (quickopsbefromquickopsbe.var.log.containers…); else the source's default service. - Kubernetes:
namespace,pod,containerandhostbecome fields (from the Kubernetes filter, or from the log file name in the tag when the filter isn't used). - JSON logs: an app that writes JSON on stdout gets its fields lifted out (
msg,level,route,trace_id, …). - Access logs:
GET /api/orders?x=1 … 503getsmethod,route(without the query string) andstatusfields, so lines can be matched to the request metrics of that route. - Redaction before storage: emails, bearer tokens,
password=/secret=/token=/api_key=values and card numbers are masked, plus your own patterns. - Limits: lines longer than
LOG_INGEST_MAX_LINE_BYTESare truncated; lines over a source's rate limit are dropped and counted.
2. The Log Browser#
Logs → Log Browser:
- Search messages (
timeout,"connection refused"; matches are highlighted). - Levels: click ERROR / WARN / INFO / DEBUG to show or hide them; each shows its count.
- Service: pick one or more services.
- LogsQL: any extra filter, e.g.
route:"/api/orders" AND status:>=500. The full query is shown under the box. - Time: 15m to 7d. Drag across the volume chart to zoom in. Go live refreshes every 3 seconds.
- Lines: newest first. Click a line for the whole message (multi-line stack traces, pretty-printed JSON), all its fields (each with only these / hide these buttons), copy buttons, and Lines around this one, which opens the lines just before and after it from the same container or file.
- Patterns: groups lines that differ only in ids, numbers, addresses or times
("Connection to
<ip>timed out after<num>ms") with counts, first and last time, and a New badge for patterns that first appeared in this time range. Show lines jumps back to the matching lines.
The URL keeps everything (query, levels, services, range), so you can share a link.
3. Logs of an endpoint#
Endpoint → Logs tab:
- Suggested log links: Pulsimo looks at the services and hosts in your logs and suggests the ones that match the endpoint's host, its route and its metric sources — including endpoints you created from metrics or the Discovered inbox. One click links them.
- Link logs with your own filter: any LogsQL filter, e.g.
service:"orders-api" AND route:"/api/orders". - The newest lines (15m to 24h, refreshed every 15 s) with a volume chart, an errors and warnings only switch, and Open in Log Browser (pre-filtered to this endpoint).
Linked logs are used everywhere else: incident evidence, probable causes, alerts and charts. They also open incidents of their own when the app keeps throwing exceptions: see Incidents from logs.
4. Logs in alerts#
"Service down" and escalation alerts for an endpoint with linked logs include its most frequent error patterns of the last 10 minutes:
What the logs show:
- 1240× pq: sorry, too many clients already (orders-api, since 14:01:31 UTC)5. Logs as metrics and changes#
Every minute Pulsimo counts lines per service and level, and the busiest error patterns:
| Series | Meaning |
|---|---|
pulsimo_log_lines_per_minute{service, level} |
Log volume, e.g. errors per minute per service |
pulsimo_log_pattern_per_minute{service, pattern, level} |
One error pattern's rate |
Chart them in dashboards or the Explorer next to latency and CPU, set SLO-style alerts on
them, or compare: sum(pulsimo_log_lines_per_minute{service="orders-api",level="error"}).
An error pattern never seen before becomes a New error change: a marker on charts, a line in the digest, and a candidate cause for incidents (Probable cause).
Settings#
| Variable | Default | Meaning |
|---|---|---|
LOGS_RETENTION |
7d |
How long lines are kept (read by the log store at startup) |
LOG_INGEST_PUBLIC_URL |
(the address the page uses) | Address Fluent Bit uses to reach Pulsimo, put into generated configs |
LOG_INGEST_MAX_LINES_PER_SEC |
2000 |
Default rate limit per source |
LOG_INGEST_MAX_LINE_BYTES |
16384 |
Longer messages are truncated |
LOG_AGENT_IMAGE |
fluent/fluent-bit:3.1 |
Fluent Bit image in generated setups |
LOG_PATTERN_INTERVAL_SECONDS |
60 |
How often patterns and log rates are computed |
LOG_PATTERN_MAX_LINES |
5000 |
Most warning/error lines read per organization per pass |
Limits#
- Lines are searchable a few seconds after they arrive.
- Patterns are computed from warnings and errors only.
- Lines older than the retention are gone; incidents keep their saved log evidence.