Skip to content
lorebow

Logs

The app writes events to standard output as a stream, and the platform collects, stores and searches them.

KFounder and editor 170 words 1 min read Find it on the map
On this page

Treat logs as event streams. A log is a stream of events, one per line, ordered by time, with no beginning or end. A twelve-factor app doesn't decide where that stream goes. It writes to standard output, and the environment it runs in takes it from there.

So the app never opens a log file, rotates one, or ships logs anywhere itself.

Where a log line goesstdoutStep 1 of 3
web.1print to stdoutweb.2print to stdoutworker.1print to stdoutCollectorplatform agentSearchLoki, ElasticAlertserror rate

1.Every process writes to stdout

Each process prints one event per line. It doesn't know or care where the line ends up.

#Why not write to a file

  • Processes are disposable. When a container is replaced, its local files go with it, along with the logs explaining why it was replaced.
  • There are many processes. Ten processes writing ten files on ten machines can't be read as one story.
  • The destination changes. Today it's your terminal, tomorrow a log service. That's a platform decision, not a code change.

#Write structured lines

Plain text is fine for a terminal, but one JSON object per line can be searched and filtered by field:

log.pypython
import json
import logging
import sys
 
class JsonFormatter(logging.Formatter):
    def format(self, record):
        return json.dumps({
            "time": self.formatTime(record),
            "level": record.levelname,
            "message": record.getMessage(),
            **getattr(record, "fields", {}),
        })
 
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(JsonFormatter())
logging.basicConfig(level=logging.INFO, handlers=[handler])
 
logging.info("order placed", extra={"fields": {"order_id": 1042, "total": 59.90}})
Outputtext
{"time": "2026-10-10 09:14:02,118", "level": "INFO", "message": "order placed", "order_id": 1042, "total": 59.9}

Locally, you read the stream in your terminal. In production, kubectl logs or docker logs reads the same stream.

Referenced by