Browse the docs
Install and administration

Logs

Trinium writes plain text to standard output and Docker does the rest, so your own collector ships the logs and Trinium never holds a monitoring key.

Reading them

terminal
docker compose logs -f trinium

That is the whole of it. Trinium writes plain text, one line per event, meant to be read by a person with no tooling at all:

2026-10-26 18:39:45Z  INFO trinium::audit: audit action="instance.started" actor_name=system actor_kind="System" object_kind="instance" outcome="Success"
2026-10-26 18:40:44Z  INFO trinium::runs: run finished status=Succeeded environment=Production kind=Live trigger=Schedule version=12 seconds=93 warnings=0 completed_at=2026-10-26T18:40:44Z run_id=01a17983-d1d9-71e0-a549-0e71e319aa08 pipeline="Daily orders"

Each line is a UTC timestamp, the level, the component that emitted it, and the message with any values attached as name=value. Anything logged while a pipeline is running also carries that run: run{run_id=… pipeline_id=…}:, so grep for one run id and you get everything about it together: staging, the worker and the notification.

There is no other format and nothing to configure. Color codes are never written, so the output is the same in a terminal, in a file, and in your monitoring system.

Log files are capped at 10 MB × 5 files per service, in compose.yaml. You do not need to configure anything, and no log will fill your disk.

Sending them to your monitoring system

Trinium never connects to a monitoring service. It writes to standard output and Docker does the rest, so no API key or endpoint is ever stored in Trinium, and this works the same whether you are on the internet or air-gapped.

Recommended: run your vendor's agent alongside Trinium. Datadog, Elastic (Filebeat), Splunk, Grafana Alloy, Fluent Bit and Vector all read container logs off the host. Create a file called compose.override.yaml beside your compose.yaml. Docker Compose loads it automatically, so docker compose up -d stays exactly the same command, and an upgrade will never overwrite it:

YAML
# compose.override.yaml — yours, not ours. Example: Datadog.
services:
  datadog:
    image: gcr.io/datadoghq/agent:7
    environment:
      DD_API_KEY: ${DD_API_KEY}
      DD_LOGS_ENABLED: "true"
      DD_LOGS_CONFIG_CONTAINER_COLLECT_ALL: "true"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
    restart: unless-stopped

The agent reads the logs; it does not replace them, so docker compose logs keeps working and the size cap still applies.

Advanced: change the log driver instead. Docker can ship logs directly to syslog, Splunk, Fluentd, Graylog or CloudWatch with no agent. Again in compose.override.yaml:

YAML
services:
  trinium:
    logging:
      driver: syslog
      options:
        syslog-address: "tcp://siem.example.com:514"

This turns off docker compose logs. That command only works with the json-file, local and journald drivers, so with any other driver you lose local log viewing, and so do we if you ask us for support. Prefer the agent above unless your policy forbids running one.

Alerting on run outcomes

Every pipeline run and every flow run writes exactly one line when it finishes, whatever ended it: it succeeded, it failed, someone cancelled it, it reached its time limit, a scheduled run could not start, or the server running it stopped. The line uses the target trinium::runs and appears within about ten seconds of the run ending:

2026-10-26 18:40:55Z  WARN trinium::runs: run finished status=Failed environment=Production kind=Live trigger=Schedule version=12 seconds=1 warnings=0 completed_at=2026-10-26T18:40:46Z run_id=01a17983-d9b8-7ad3-8809-28074dc77f83 pipeline="Daily orders" error="Node 'Load' failed: ..."
2026-10-26 18:40:55Z  INFO trinium::runs: flow run finished status=Succeeded environment=Production trigger=Schedule seconds=1840 completed_at=2026-10-26T18:40:51Z flow_run_id=01a17983-e1a4-78d3-b010-694476557b30 flow="Nightly load"
FieldWhat it holds
statusSucceeded, Failed or Cancelled. A failed run is logged as WARN, every other outcome as INFO.
environmentStaging or Production.
kindLive, or Test for a Test run. Pipeline runs only.
triggerManual, Schedule or Flow (a pipeline run started by a flow).
versionThe version a Live run ran. Absent on a Test run.
secondsHow long it ran. Absent when it never started.
warningsHow many warnings it wrote.
completed_atWhen it ended, in UTC.
run_id / flow_run_idThe run, as the Runs page and the API name it.
pipeline / flowThe name, in quotes.
valuesThe text parameter values it ran with, such as region = US.
errorWhy it failed or stopped, in quotes, on the same line even when the message has several lines.

A field with nothing to report is left out rather than written empty. Like the audit feed, this line cannot be switched off by a log-level setting.

Email, Slack and Discord notifications cover scheduled runs and flows. This line covers every run, including runs started by hand and the pipeline runs inside a flow, so it is the one to build a monitor on. Runs that ended more than an hour before Trinium could write their line (while it was stopped, or before a restore) are not written, so a restart never replays old history into your monitor.

To alert on a failed run, match the two words trinium::runs and status=Failed:

  • Amazon CloudWatch: with the lines in a log group (the CloudWatch agent, or Docker's awslogs driver), create a metric filter with the pattern "trinium::runs" "status=Failed", then an alarm on that metric that notifies an SNS topic.
  • Azure Monitor: with the lines in a Log Analytics workspace (the Azure Monitor Agent's text log collection, or Fluent Bit), create a log search alert rule on a query such as TriniumLogs_CL | where RawData has "trinium::runs" and RawData has "status=Failed".
  • Datadog: a log monitor on the query "trinium::runs" "status=Failed". To filter and chart by pipeline or environment, add a Grok parser to the log pipeline with the rule run %{data::keyvalue}.
  • Splunk: fields written as name=value are extracted automatically at search time, so "trinium::runs" status=Failed finds them.
  • Vector: the transform below turns every line into named fields. It is what we tested the line against.
YAML
transforms:
  trinium_runs:
    type: remap
    inputs: [trinium]
    source: |
      parsed, err = parse_regex(.message, r'^(?P<ts>\S+ \S+)\s+(?P<level>[A-Z]+) (?P<target>\S+): (?P<event>run finished|flow run finished) (?P<kv>.*)$')
      if err == null {
        . = merge(parsed, parse_key_value!(parsed.kv))
        del(.kv)
      }

The audit feed

Every action that changes something (sign-ins and failed sign-ins, role changes, connection and pipeline edits, backups taken and downloaded, settings changes) is written to the audit trail, which Enterprise shows under Settings → Audit, and is also emitted on the log stream under the target trinium::audit. That is what to point at a SIEM:

terminal
docker compose logs trinium | grep trinium::audit

Each line names the action, who did it, what it was done to, and whether it succeeded, failed or was refused. Secrets are never included: a changed password or key is recorded as the fact that it changed, never as a value.

Two things worth knowing. The audit feed cannot be switched off by a log-level setting, so it keeps flowing even while you are debugging something else. And it is a copy: the trail in the database remains the record of truth, so if your collector is down for an hour you have lost nothing: every entry is still there, and on Enterprise Settings → Audit shows them and exports them as CSV.