Berserk Docs

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: 30s

Vector

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: 30

Wire 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 labelBerserk resource attribute
service_name, serviceservice.name
service_namespaceservice.namespace
service_instance_id, instanceservice.instance.id
namespace, pod, container, node_namek8s.namespace.name, k8s.pod.name, k8s.container.name, k8s.node.name
k8s_namespace_name, k8s_pod_name, k8s_container_name, k8s_cluster_nameCorresponding k8s.*.name attribute
k8s_deployment_name, k8s_replicaset_name, k8s_statefulset_name, k8s_daemonset_name, k8s_cronjob_name, k8s_job_name, k8s_node_nameCorresponding k8s.*.name attribute
container_namecontainer.name
cloud_availability_zone, cloud_regioncloud.availability_zone, cloud.region
deployment_environment_namedeployment.environment.name
filenamelog.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.

On this page