Chapter 1. LokiStack data model and log format
Understand how LokiStack structures and formats log data, including field mappings and metadata labels.
1.1. Loki output format and label extraction Copy linkLink copied to clipboard!
When you forward logs to Loki or LokiStack, the log collector transforms OpenShift log records into Loki’s stream-based format. Understanding this transformation helps you write efficient LogQL queries and configure retention policies.
Loki stores logs as streams, where each stream is identified by a unique set of labels. The log collector extracts specific fields from OpenShift log records to use as Loki labels, while the remaining fields become the log line content.
1.1.1. Loki data model Copy linkLink copied to clipboard!
Loki organizes logs into the following components:
- Stream
- A set of log entries that share the same labels. Each unique combination of labels creates a separate stream.
- Labels
- Indexed metadata used to identify and query streams. Labels are extracted from the OpenShift log record’s Kubernetes metadata and log type fields.
- Log line
- The log message content, stored as a string. The log line can be structured JSON or plain text.
- Timestamp
-
The time when the log entry was created, extracted from the log record’s
@timestampfield.
1.1.2. Label extraction Copy linkLink copied to clipboard!
The log collector automatically extracts the following fields as Loki labels:
| Label name | Source field |
|---|---|
|
|
Log record type: |
|
|
|
|
|
|
|
|
|
|
|
|
For infrastructure journal logs, the collector also extracts:
| Label name | Source field |
|---|---|
|
|
|
For audit logs, the collector extracts:
| Label name | Source field |
|---|---|
|
|
|
|
|
|
Loki performs best with a limited number of label combinations (cardinality). Each unique set of labels creates a new stream, which increases storage requirements and query processing time. The default label extraction provides good query performance while keeping cardinality manageable.
Avoid adding high-cardinality labels (for example, unique request IDs, timestamps, or user-specific identifiers) as they create excessive streams and degrade Loki performance.
1.1.3. Log line format Copy linkLink copied to clipboard!
After label extraction, the log collector serializes the remaining fields as the log line content. For structured logs, this is JSON. For plain text logs, this is the message string.
The following OpenShift log record:
{
"kubernetes": {
"namespace_name": "my-app",
"pod_name": "web-1",
"container_name": "nginx",
"host": "ip-10-0-1-42.ec2.internal"
},
"message": "Error connecting to database",
"level": "error",
"@timestamp": "2024-01-15T10:30:00.000Z"
}
The log collector transforms this into a Loki stream entry:
Labels:
{
log_type="application",
kubernetes_namespace_name="my-app",
kubernetes_pod_name="web-1",
kubernetes_container_name="nginx",
kubernetes_host="ip-10-0-1-42.ec2.internal"
}
Log line (remaining fields as JSON):
{
"message": "Error connecting to database",
"level": "error",
"@timestamp": "2024-01-15T10:30:00.000Z"
}
Timestamp: 2024-01-15T10:30:00.000Z
The following infrastructure log from systemd journal:
{
"message": "Started container",
"systemd": {
"t": {
"SYSTEMD_UNIT": "kubelet.service"
}
},
"hostname": "ip-10-0-1-42.ec2.internal",
"@timestamp": "2024-01-15T10:30:00.000Z"
}
The log collector transforms this into a Loki stream entry:
Labels:
{
log_type="infrastructure",
systemd_unit="kubelet.service",
kubernetes_host="ip-10-0-1-42.ec2.internal"
}
Log line:
{
"message": "Started container",
"@timestamp": "2024-01-15T10:30:00.000Z"
}
1.1.4. Querying Loki logs Copy linkLink copied to clipboard!
Use LogQL to query logs in Loki. Labels enable efficient stream selection:
Query all application logs from a specific namespace:
{log_type="application", kubernetes_namespace_name="my-app"}
Query logs from a specific pod:
{kubernetes_namespace_name="my-app", kubernetes_pod_name="web-1"}
Query infrastructure logs from kubelet:
{log_type="infrastructure", systemd_unit="kubelet.service"}
After selecting streams by labels, you can filter log lines by content:
Query application logs containing "error":
{log_type="application"} |= "error"
Query logs with JSON field matching a value:
{log_type="application"} | json | level="error"