Berserk Docs

Grafana

Connect Grafana to Berserk using the Berserk datasource plugin

The Berserk datasource plugin lets you query Berserk directly from Grafana dashboards using KQL.

Download the latest release for your platform from the GitHub releases page. Archives are available for Linux (x64, ARM64, ARM) and macOS (x64, ARM64).

Installation

Extract the plugin

Unzip the downloaded archive into your Grafana plugins directory:

unzip berserk-datasource-*.zip -d /var/lib/grafana/plugins/

Allow unsigned plugin

Since the plugin is not signed, add it to the allow list in your Grafana configuration (grafana.ini or environment variable):

[plugins]
allow_loading_unsigned_plugins = berserk-datasource

Or with an environment variable:

GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=berserk-datasource

Restart Grafana

Restart Grafana to load the plugin.

Add the datasource

In Grafana, go to Connections > Data sources > Add data source and search for Berserk. Set the URL to your Berserk cluster, which listens on port 9500 by default.

Set the service token

Berserk authenticates every request, so the datasource needs a service token. Create a service principal and mint a token with the CLI:

bzrk service-account create grafana --display-name "Grafana"
bzrk service-account token create grafana grafana-token

You can also create a service principal and token from the Service Accounts page in the Berserk admin UI.

Paste the resulting bzrk_sp_… token into the datasource's Service token field, then click Save & test (the health check verifies both reachability and the token). When provisioning Grafana from config, set it under secureJsonData.serviceToken rather than jsonData.

Authentication

Berserk authenticates every request at the gateway — the only authenticated edge, reachable on port 9500. The datasource authenticates as a service principal: it sends the service token as a bearer credential on each call, and the gateway resolves that token to a trusted identity before forwarding the request to the query engine. Every query from one datasource runs as that single service principal — there are no per-user credentials.

Set the token in the datasource's Service token field, as shown in Set the service token above. Grafana stores it encrypted under secureJsonData.serviceToken; it is never written to plain jsonData and cannot be read back through the API. Point the datasource URL (and, when provisioning, clusterUrl) at the gateway, not directly at the query service.

Provisioning from config

Supply the token from an environment variable backed by a secret rather than committing it:

datasources:
  - name: Berserk
    type: berserk-datasource
    access: proxy
    jsonData:
      clusterUrl: http://gateway.bzrk.svc.cluster.local:9500
    secureJsonData:
      serviceToken: $BERSERK_SERVICE_TOKEN

Rotating a token

Mint a fresh token, paste it into the datasource (or update the provisioned secret), then remove the old one from the Service Accounts page in the Berserk admin UI. Disabling the service principal there immediately blocks every datasource using its tokens.

A service principal can hold broad query access. Scope it to the databases the dashboards need, and use a separate service principal per Grafana instance so a leaked token can be revoked without disrupting the others.

Querying

The plugin supports KQL queries. Write your query in the editor and select a table from the dropdown. The plugin supports:

  • Table format for log and trace data
  • Time series for metrics and summarize ... by bin(Timestamp, ...) queries
  • Alerting via Grafana alert rules
  • Streaming for live tail queries
  • Template variables for dynamic dashboards

Time Filter Macros

Panel and alert queries are automatically scoped to the dashboard's selected time range — the datasource forwards the range to Berserk, which applies it server-side, so a time filter is rarely needed.

A few cases still call for one: template-variable and annotation queries are not auto-scoped, and filtering on a custom datetime column needs the macro explicitly. The macros below cover those.

The macros below are still available for explicit control (for example, filtering on a custom datetime column). They are replaced with the dashboard's time range before the query is sent to Berserk:

MacroExpands toDescription
$__timeFiltertimestamp >= datetime(...) and timestamp <= datetime(...)Filter on the default timestamp column
$__timeFilter(col)col >= datetime(...) and col <= datetime(...)Filter on a custom datetime column
$__timeFromdatetime(2025-01-01T00:00:00Z)Start of the selected time range
$__timeTodatetime(2025-01-01T06:00:00Z)End of the selected time range
$__timeInterval5000msRecommended bin size based on the time range and panel width

Use bin_auto(timestamp) to automatically choose a bin size based on the time range, or bin_auto(timestamp, 10m) to set a minimum bin size.

Example Queries

Count events over time by category:

default
| summarize count() by category, bin_auto(timestamp)
| sort by timestamp

Average and p95 latency over time:

default
| where resource.service.name == "my-service"
| summarize
    avg_duration=avg(toint(duration_ms)),
    p95_duration=percentile(toint(duration_ms), 95)
    by bin_auto(timestamp)
| sort by timestamp

Top pages by count:

default
| where name == "page_view"
| summarize count=count() by url.path
| sort by count desc
| take 20

Error log table:

default
| where severity >= 3
| project timestamp, resource.service.name, body, error.message
| sort by timestamp desc
| take 100

Parse structured log messages:

default
| where body contains "throughput"
| parse tostring(body) with "Local throughput: " Throughput:double " MB" *
| summarize min(Throughput), max(Throughput) by bin_auto(timestamp)

On this page