Loki clients
Send logs to Berserk with Grafana Alloy, Promtail or Vector
Berserk serves the Loki Push API at POST /loki/api/v1/push, for existing Loki clients. The OTLP API over gRPC is recommended and more efficient (OpenTelemetry Collector).
Copy your installation's Loki Base URL from Settings → Endpoints. Use a Berserk ingest token as the bearer token; its routing decides the database and table. A Loki tenant header does not select a Berserk database.
Where the Loki Push API is published
Managed Berserk does not publish the Loki Push API; ask the Berserk team if you need it. On a self-hosted install its listener is on by default, and the operator routes it and publishes its address: Loki Push API.
Grafana Alloy
Add a loki.write component and connect your existing log source's forward_to to loki.write.berserk.receiver. The url takes the full push URL, including the path:
loki.write "berserk" {
endpoint {
url = "https://<your-loki-host>/loki/api/v1/push"
bearer_token = "<ingest token>"
remote_timeout = "30s"
}
}For example, a file source can feed this writer:
loki.source.file "app" {
targets = [{
__path__ = "/var/log/my-app/*.log",
service_name = "my-app",
}]
forward_to = [loki.write.berserk.receiver]
}Existing Promtail installations
Replace or add a client in your existing Promtail configuration. Keep your scrape_configs and positions file. This is a client fragment:
clients:
- url: https://<your-loki-host>/loki/api/v1/push
bearer_token: "<ingest token>"
timeout: 30sVector
Connect your existing log source to this sink by replacing my_logs. Vector's endpoint takes the base URL and appends the push path:
sinks:
berserk:
type: loki
inputs: [my_logs]
endpoint: https://<your-loki-host>
auth:
strategy: bearer
token: "<ingest token>"
labels:
service_name: my-app
encoding:
codec: text
request:
timeout_secs: 30Wire format and responses
Send Content-Type: application/json for a Loki push JSON envelope, with streams, stream labels and timestamp/string pairs. Timestamps are decimal nanoseconds encoded as strings. Arbitrary JSON log objects are not this envelope.
For Protobuf, use Content-Type: application/x-protobuf and Snappy block compression. The Snappy encoding is part of the Loki push format, without a Content-Encoding header. Alloy and Promtail provide this encoding themselves.
A successful request returns 204 with no body, or 202 with no body when the installation acknowledges on receipt (acknowledgement). Retries and buffering follow delivery semantics.
Label mapping
Recognized labels become resource attributes; other labels become log record attributes. Severity labels set the record's severity, and exporter is discarded.
| Loki label | Berserk resource attribute |
|---|---|
service_name, service | service.name |
service_namespace | service.namespace |
service_instance_id, instance | service.instance.id |
namespace, pod, container, node_name | k8s.namespace.name, k8s.pod.name, k8s.container.name, k8s.node.name |
k8s_namespace_name, k8s_pod_name, k8s_container_name, k8s_cluster_name | Corresponding k8s.*.name attribute |
k8s_deployment_name, k8s_replicaset_name, k8s_statefulset_name, k8s_daemonset_name, k8s_cronjob_name, k8s_job_name, k8s_node_name | Corresponding k8s.*.name attribute |
container_name | container.name |
cloud_availability_zone, cloud_region | cloud.availability_zone, cloud.region |
deployment_environment_name | deployment.environment.name |
filename | log.file.path |
job supplies service.name when no explicit service label exists. A job of namespace/service also supplies service.namespace. level sets severity. Structured metadata becomes record attributes. Underscores become dots only where the resulting key starts with a recognized OpenTelemetry prefix: service., k8s., host., container., cloud., deployment., process., os., log., http., net. or telemetry.. Other keys retain their spelling.
Send and find a test log
Replace the host and token. The command stamps the current time:
curl --fail-with-body -w '\nHTTP %{http_code}\n' \
'https://<your-loki-host>/loki/api/v1/push' \
-H 'Authorization: Bearer <ingest token>' \
-H 'Content-Type: application/json' \
-d '{"streams":[{"stream":{"service_name":"ingest-test","level":"info"},"values":[["'"$(date +%s)"'000000000","Hello from Berserk"]]}]}'In Berserk, query the token's log table for a recent window, filtered on service.name == "ingest-test". If no record appears, check the token's routing in Settings → Databases → Tokens.