Application Observability with Grafana Alloy
Grafana Alloy is a vendor-neutral distribution of the OpenTelemetry (OTel) Collector and the recommended way to send OpenTelemetry data to Grafana Cloud. Grafana Alloy acts as an outbound gateway providing reliability and scalability.
Before you begin
To set up Grafana Alloy as a data collector and send data to Grafana Cloud:
- Create and/or login to a Grafana Cloud account
- Install Grafana Alloy or use an existing install
Grafana requires you to run Alloy on every host for Application Observability to function optimally. This also allows Grafana to seamlessly correlate data between Application and Infrastructure observability.
If you’ve already set up a Collector, configure your application to use it.
Configure Alloy
You need an alloy-config.river
configuration file to run Grafana Alloy in flow mode and it’s recommended to use the OpenTelemetry (OTLP) integration to generate a configuration file.
Navigate to the OpenTelemetry Application page and click the Add service button. Choose the OpenTelemetry (OTLP) integration from the list.
The OpenTelemetry (OTLP) integration will generate a Grafana Alloy configuration to use with Grafana Application Observability:
otelcol.receiver.otlp "default" {
// https://grafana.com/docs/alloy/latest/reference/components/otelcol.receiver.otlp/
// configures the default grpc endpoint "0.0.0.0:4317"
grpc { }
// configures the default http/protobuf endpoint "0.0.0.0:4318"
http { }
output {
metrics = [otelcol.processor.resourcedetection.default.input]
logs = [otelcol.processor.resourcedetection.default.input]
traces = [otelcol.processor.resourcedetection.default.input]
}
}
otelcol.processor.resourcedetection "default" {
// https://grafana.com/docs/alloy/latest/reference/components/otelcol.processor.resourcedetection/
detectors = ["env", "system"] // add "gcp", "ec2", "ecs", "elastic_beanstalk", "eks", "lambda", "azure", "aks", "consul", "heroku" if you want to use cloud resource detection
system {
hostname_sources = ["os"]
}
output {
metrics = [otelcol.processor.transform.drop_unneeded_resource_attributes.input]
logs = [otelcol.processor.transform.drop_unneeded_resource_attributes.input]
traces = [otelcol.processor.transform.drop_unneeded_resource_attributes.input]
}
}
otelcol.processor.transform "drop_unneeded_resource_attributes" {
// https://grafana.com/docs/alloy/latest/reference/components/otelcol.processor.transform/
error_mode = "ignore"
trace_statements {
context = "resource"
statements = [
"delete_key(attributes, \"k8s.pod.start_time\")",
"delete_key(attributes, \"os.description\")",
"delete_key(attributes, \"os.type\")",
"delete_key(attributes, \"process.command_args\")",
"delete_key(attributes, \"process.executable.path\")",
"delete_key(attributes, \"process.pid\")",
"delete_key(attributes, \"process.runtime.description\")",
"delete_key(attributes, \"process.runtime.name\")",
"delete_key(attributes, \"process.runtime.version\")",
]
}
metric_statements {
context = "resource"
statements = [
"delete_key(attributes, \"k8s.pod.start_time\")",
"delete_key(attributes, \"os.description\")",
"delete_key(attributes, \"os.type\")",
"delete_key(attributes, \"process.command_args\")",
"delete_key(attributes, \"process.executable.path\")",
"delete_key(attributes, \"process.pid\")",
"delete_key(attributes, \"process.runtime.description\")",
"delete_key(attributes, \"process.runtime.name\")",
"delete_key(attributes, \"process.runtime.version\")",
]
}
log_statements {
context = "resource"
statements = [
"delete_key(attributes, \"k8s.pod.start_time\")",
"delete_key(attributes, \"os.description\")",
"delete_key(attributes, \"os.type\")",
"delete_key(attributes, \"process.command_args\")",
"delete_key(attributes, \"process.executable.path\")",
"delete_key(attributes, \"process.pid\")",
"delete_key(attributes, \"process.runtime.description\")",
"delete_key(attributes, \"process.runtime.name\")",
"delete_key(attributes, \"process.runtime.version\")",
]
}
output {
metrics = [otelcol.processor.transform.add_resource_attributes_as_metric_attributes.input]
logs = [otelcol.processor.batch.default.input]
traces = [
otelcol.processor.batch.default.input,
otelcol.connector.host_info.default.input,
]
}
}
otelcol.connector.host_info "default" {
// https://grafana.com/docs/alloy/latest/reference/components/otelcol.connector.host_info/
host_identifiers = ["host.name"]
output {
metrics = [otelcol.processor.batch.default.input]
}
}
otelcol.processor.transform "add_resource_attributes_as_metric_attributes" {
// https://grafana.com/docs/alloy/latest/reference/components/otelcol.processor.transform/
error_mode = "ignore"
metric_statements {
context = "datapoint"
statements = [
"set(attributes[\"deployment.environment\"], resource.attributes[\"deployment.environment\"])",
"set(attributes[\"service.version\"], resource.attributes[\"service.version\"])",
]
}
output {
metrics = [otelcol.processor.batch.default.input]
}
}
otelcol.processor.batch "default" {
// https://grafana.com/docs/alloy/latest/reference/components/otelcol.processor.batch/
output {
metrics = [otelcol.exporter.otlphttp.grafana_cloud.input]
logs = [otelcol.exporter.otlphttp.grafana_cloud.input]
traces = [otelcol.exporter.otlphttp.grafana_cloud.input]
}
}
otelcol.exporter.otlphttp "grafana_cloud" {
// https://grafana.com/docs/alloy/latest/reference/components/otelcol.exporter.otlphttp/
client {
endpoint = env("GRAFANA_CLOUD_OTLP_ENDPOINT")
auth = otelcol.auth.basic.grafana_cloud.handler
}
}
otelcol.auth.basic "grafana_cloud" {
// https://grafana.com/docs/alloy/latest/reference/components/otelcol.auth.basic/
username = env("GRAFANA_CLOUD_INSTANCE_ID")
password = env("GRAFANA_CLOUD_API_KEY")
}
The configuration file requires several environmental variable to be set:
Environment Variable | Description | Example |
---|---|---|
GRAFANA_CLOUD_API_KEY | API key generated above | eyJvSomeLongStringJ9fQ== |
GRAFANA_CLOUD_OTLP_ENDPOINT | OTLP endpoint from Grafana Cloud > OpenTelemetry > Configure | https://otlp-endpoint-***.grafana.net/otlp |
GRAFANA_CLOUD_INSTANCE_ID | Instance ID from Grafana Cloud > OpenTelemetry > Configure | 11111 |
Run Grafana Alloy
Create the alloy-config.river
file, set the necessary environment variables, and run Grafana Alloy.
Configure your application
Set the following environment variables to configure the Collector for your application:
Configuration | Options | Result |
---|---|---|
export OTEL_EXPORTER_OTLP_ENDPOINT=<host> | http://localhost:4318 , remote host address | The default local host address, or a remote host address. |
export OTEL_EXPORTER_OTLP_PROTOCOL=<protocol> | grpc , http/protobuf | The default http/protobuf protocol or grpc |
For example, for a local Grafana Alloy set the following environment variables:
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
Then restart your application.