Skip to main content

Grafana Alloy

Grafana Alloy is a vendor-neutral telemetry collector that uses the River configuration language. It can scrape Prometheus exporters, receive OTLP data, and forward everything to xScaler over remote_write.

:::warning Required headers Both headers are mandatory on every request:

  • Authorization: Bearer <token>. Set via the authorization block
  • X-Scope-OrgID: <tenant-id>. Set via the headers map :::

Configuration

Save the following as config.alloy:

// Collect host metrics via the unix exporter
prometheus.exporter.unix "host" {}

prometheus.scrape "host_metrics" {
targets = prometheus.exporter.unix.host.targets
forward_to = [prometheus.remote_write.xscaler.receiver]
scrape_interval = "15s"
}

prometheus.remote_write "xscaler" {
endpoint {
url = "https://euw1-01.m.xscalerlabs.com/api/v1/push"

authorization {
type = "Bearer"
credentials = "<token>"
}

headers = {
"X-Scope-OrgID" = "<tenant-id>",
}

queue_config {
capacity = 10000
max_samples_per_send = 2000
batch_send_deadline = "5s"
min_shards = 1
max_shards = 10
min_backoff = "30ms"
max_backoff = "5s"
}
}
}

River syntax notes

  • River uses = for assignment, not :.
  • Blocks are delimited by { }, not by indentation.
  • The authorization block takes type and credentials as separate fields.
  • headers is a string map. Keys and values are both quoted strings.
  • The forward_to reference in prometheus.scrape wires the scrape output directly to the remote_write receiver. The label xscaler must match the label on prometheus.remote_write.

Load credentials from environment variables

Avoid storing secrets in the config file by reading them at runtime:

prometheus.remote_write "xscaler" {
endpoint {
url = "https://euw1-01.m.xscalerlabs.com/api/v1/push"

authorization {
type = "Bearer"
credentials = env("XSCALER_TOKEN")
}

headers = {
"X-Scope-OrgID" = env("XSCALER_TENANT_ID"),
}
}
}

Run with Docker

docker run --rm \
-e XSCALER_TOKEN=<token> \
-e XSCALER_TENANT_ID=<tenant-id> \
-v $(pwd)/config.alloy:/etc/alloy/config.alloy \
grafana/alloy:latest \
run /etc/alloy/config.alloy

Troubleshooting

Metrics not arriving

  1. Enable debug logging by adding --stability.level=generally-available to the alloy run command and checking stdout for errors.
  2. Open the Alloy UI at http://localhost:12345. It shows the health status of every component. A red component means it has encountered an error.
  3. Verify the headers block includes "X-Scope-OrgID". This is the most common cause of 401 x-scope-orgid mismatch errors.
  4. Confirm the authorization block uses type = "Bearer" and credentials = "<token>" (not a bare bearer_token field at the top level when using the block form).

401 Unauthorized: "x-scope-orgid mismatch" The X-Scope-OrgID key is missing from the headers map, or its value doesn't match your token's tenant. Add or correct it and restart Alloy.

401 Unauthorized Check the credentials value. It must be the raw token string, not Bearer <token>. Alloy adds the type = "Bearer" prefix itself.