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 theauthorizationblockX-Scope-OrgID: <tenant-id>. Set via theheadersmap :::
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
authorizationblock takestypeandcredentialsas separate fields. headersis a string map. Keys and values are both quoted strings.- The
forward_toreference inprometheus.scrapewires the scrape output directly to theremote_writereceiver. The labelxscalermust match the label onprometheus.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
- Enable debug logging by adding
--stability.level=generally-availableto thealloy runcommand and checking stdout for errors. - 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. - Verify the
headersblock includes"X-Scope-OrgID". This is the most common cause of401 x-scope-orgid mismatcherrors. - Confirm the
authorizationblock usestype = "Bearer"andcredentials = "<token>"(not a barebearer_tokenfield 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.