Skip to content
ExponaBLOG
PROMETHEUS, GRAFANA & MONITORING · DAY 096 / 100

Grafana Alloy: what every Monitoring developer should know

A unified telemetry collector.

Expona Admin6 min read

Grafana Alloy: what every Monitoring developer should know

If you're managing a modern observability stack, you've likely felt the friction of juggling multiple agents and collectors across your infrastructure. Grafana Alloy is a unified telemetry collector that consolidates what used to require separate tools, reducing operational complexity while giving you more control over how telemetry flows through your system. We'll walk you through what makes it different, how it works in practice, and where it fits into your monitoring architecture.

Why Alloy matters now

For years, the observability ecosystem fragmented around specialized tools: Prometheus Scraper for metrics, Promtail for logs, and OpenTelemetry Collector or various agents for traces. Teams ended up running 3–5 different agents per host, each with its own configuration format, memory footprint, and upgrade cycle. Grafana Alloy consolidates that scatter into a single, composable binary.

The shift matters because operational overhead compounds. Each extra agent you run means more deployment automation, more version management, more debugging when things go sideways. Alloy's unified model doesn't just save CPU cycles—it simplifies how your team reasons about data flow. One config, one observability story, one place to troubleshoot.

Collects metrics, logs and traces

Grafana Alloy ingests all three telemetry types through a single runtime. That doesn't mean it's generic or watered-down; it's intentionally designed to handle the specific semantics of each signal type.

Metrics collection builds on Prometheus's scrape logic. You define targets, scrape intervals, relabeling rules—all the patterns you already know. Alloy can scrape Prometheus endpoints, ingest metrics via OpenTelemetry gRPC receivers, or consume Graphite-formatted data. Cardinality awareness and label manipulation work the same way you've configured them in Prometheus.

Log collection replaces Promtail's role. Instead of teaching teams yet another config syntax, Alloy uses the same pipeline model for logs as it does for metrics. You define sources (file tails, syslog, journald, HTTP push receivers), parse and filter them, then ship to Loki or your chosen backend. Structured fields extract cleanly, and you can enrich logs with resource attributes before sending.

Trace collection handles the full OpenTelemetry spectrum. Alloy can receive traces via OTLP gRPC and HTTP, Jaeger gRPC, Zipkin, and other formats. You can sample, batch, and enrich traces before forwarding to Grafana Tempo, Jaeger, or any OTLP-compatible endpoint. Trace-to-metrics generation (RED metrics from traces) happens natively, closing the loop between signal types.

Because metrics, logs, and traces flow through the same collector process, you can correlate signals with shared context. A single configuration change propagates across all three pipelines. That unified approach eliminates the mental tax of context-switching between agent models.

Replaces Grafana Agent and Promtail

Grafana Agent and Promtail served their purpose, but they were point solutions. Grafana Agent focused on metrics and traces with basic log support. Promtail was logs-only. Teams combining both paid a real cost: separate deployments, separate configs, separate observability for the agents themselves.

Alloy is the intentional successor to both. If you're running Grafana Agent today, Alloy is a drop-in replacement with a slightly different configuration language (we'll cover that next). If you're running Promtail, you can consolidate log collection into the same Alloy binary already scraping your Prometheus endpoints.

Migration paths are straightforward. Grafana provides conversion tools and side-by-side deployment guides. Most teams test Alloy in parallel with existing agents on a canary set of hosts, then roll out gradually. The unified binary tends to run leaner than two agents combined, so you often see memory and CPU wins even before optimizing the configuration.

One practical note: Alloy's configuration is written in Grafana's own HCL-like syntax called Alloy configuration language, not YAML. That's a deliberate choice—the language supports better composition, variable scoping, and conditional logic than YAML alone. If your team is heavily invested in YAML, there's a learning curve, but it pays off when you start building reusable modules and complex data transformation pipelines.

Pipelines defined in config

The heart of Alloy is its pipeline model. You compose pipelines by connecting components that receive, transform, and export telemetry. Think of it as a DAG (directed acyclic graph) where each node is a component, and edges represent data flow.

A typical metrics pipeline looks like this:

yaml
prometheus.scrape "default" {
  targets = [
    {
      __address__ = "localhost:9090",
      job = "prometheus",
    },
  ]
  scrape_interval = "15s"
  forward_to = [prometheus.relabel.drop_internal.receiver]
}

prometheus.relabel "drop_internal" {
  rule {
    action        = "drop"
    source_labels = ["__name__"]
    regex         = "go_.*"
  }
  forward_to = [prometheus.remote_write.cortex.receiver]
}

prometheus.remote_write "cortex" {
  endpoint = "http://cortex:9009/api/prom/push"
}

For logs, the pipeline is equally straightforward:

yaml
loki.source.file "app_logs" {
  targets = [{
    __path__ = "/var/log/app/*.log",
    service  = "myapp",
  }]
  forward_to = [loki.process.parse.receiver]
}

loki.process "parse" {
  stage {
    json {
      expressions = {
        level = "level",
        msg   = "message",
      }
    }
  }
  forward_to = [loki.write.default.receiver]
}

loki.write "default" {
  clients = [{
    url = "http://loki:3100/loki/api/v1/push"
  }]
}

The same principle applies to traces. Define a source, apply transformations (sampling, batching, attribute addition), then export. Components are chainable and reusable. You can nest pipelines, conditionally route data, and even loop back outputs into other processors.

This declarative, component-based approach beats imperative agent configuration because changes are visible at a glance. Debugging is easier—you inspect each component's input and output. Testing new transformations means updating a single config block and reloading, often without restarting the agent.

Send to any backend

Alloy exports are not locked into Grafana's stack. You can send metrics to Prometheus, Cortex, Mimir, or any Prometheus-compatible remote write endpoint. Logs go to Loki, Datadog, Splunk, CloudWatch, or any syslog-compatible receiver. Traces reach Tempo, Jaeger, Honeycomb, Lightstep, New Relic, or any OTLP backend.

That flexibility matters because real-world deployments rarely use one vendor for everything. Maybe you use Prometheus for infrastructure metrics but Datadog for application performance. Alloy collects everything in one place and multiplexes to each backend independently.

yaml
prometheus.remote_write "prometheus" {
  endpoint = "http://prometheus:9009/api/v1/write"
}

prometheus.remote_write "cortex" {
  endpoint = "https://cortex-blocks.prod.us-west-2.amazonaws.com/api/prom/push"
  basic_auth {
    username = env("CORTEX_USER")
    password = env("CORTEX_PASS")
  }
}

prometheus.scrape "default" {
  targets = [{
    __address__ = "localhost:9100",
  }]
  forward_to = [
    prometheus.remote_write.prometheus.receiver,
    prometheus.remote_write.cortex.receiver,
  ]
}

The same pattern holds for logs and traces. You define multiple sinks and fan out to each. Alloy handles batching, retries, and backpressure per backend, so a slow or failing endpoint doesn't starve others.

This multi-sink capability is powerful for migration scenarios. Run Alloy in parallel with your current observability pipeline, send to both old and new backends, then flip the switch when you're confident. No forklift cutover required.

Common mistakes

Treating Alloy like a static configuration. Alloy's real power emerges when you treat configuration as code. Use templates, conditionals, and variables to avoid repetition across environments. A flat, non-modular config quickly becomes unmaintainable.

Underestimating cardinality impact. Alloy makes it easy to collect everything, but high-cardinality metrics (especially with relabeling) can blow up your backend. Implement cardinality limits and sampling strategies early. Test pipelines against realistic label combinations before production deployment.

Forgetting to instrument Alloy itself. Alloy exposes its own runtime metrics (up, scrapes, errors, memory). Bind these to a scrape target and monitor the monitor. You'll catch configuration drift, memory leaks, and exporter failures faster.

Ignoring batching and retry configuration. Default batching settings work for light loads but cause latency or data loss under pressure. Tune batch size, timeout, and retry policy per backend based on your throughput and tolerance for transient failures.

Key takeaways

  • Grafana Alloy unifies metrics, logs, and traces collection into one binary, replacing separate Grafana Agent and Promtail deployments and reducing operational complexity.
  • Pipelines are defined declaratively in Alloy's configuration language, making data flows transparent and changes auditable without restarts in many cases.
  • Multi-sink support lets you fan out telemetry to multiple backends simultaneously, enabling gradual migrations and multi-vendor architectures.
  • Component-based composition, variable scoping, and reusable modules make Alloy configuration scalable and testable at team scale.
  • Cardinality management and Alloy's own instrumentation must be built in from day one; defaulting to "collect everything" creates cost and stability issues later.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles