From grafana-app-sdk
Guides setup of Grafana Beyla eBPF auto-instrumentation for HTTP/gRPC/DB observability in Go, Java, Python, Ruby, Node.js, .NET, Rust, PHP, C/C++ apps without code changes. Covers Kubernetes deployment, OTLP traces to Tempo, Prometheus metrics export.
npx claudepluginhub grafana/skills --plugin grafana-app-sdkThis skill uses the workspace's default tool permissions.
> **Docs**: https://grafana.com/docs/beyla/latest/
Instruments apps with OpenTelemetry SDKs in Go, Java, Python, Node.js, .NET; configures OTLP endpoints to Grafana Cloud, Alloy collectors, Kubernetes Operator, sampling, and migrations.
Instruments apps with OpenTelemetry for distributed tracing and Jaeger/Tempo integration. Debugs latency in microservices, analyzes request flows, correlates traces with logs/metrics.
Instrument a service with OpenTelemetry — RED metrics, structured logs, distributed tracing, and health checks. Outputs actual code and config, not a plan. Use when asked to "add monitoring", "instrument this", "add logging", "set up tracing", or "observability".
Share bugs, ideas, or general feedback.
Beyla is a Grafana eBPF auto-instrumentation tool that captures HTTP/gRPC traffic and generates traces and metrics without modifying application code.
CAP_SYS_ADMIN; in Kubernetes must run in host PID namespaceCheck BTF support:
ls /sys/kernel/btf/vmlinux # must exist
| Language | HTTP | gRPC | DB queries |
|---|---|---|---|
| Go | ✅ | ✅ | ✅ |
| Java (JVM) | ✅ | ✅ | ✅ |
| Python | ✅ | ✅ | - |
| Ruby | ✅ | - | - |
| Node.js | ✅ | - | - |
| .NET | ✅ | ✅ | - |
| Rust | ✅ | ✅ | - |
| C/C++ | ✅ | - | - |
| PHP | ✅ | - | - |
# Docker
docker run --privileged --pid=host \
-v /sys/kernel/debug:/sys/kernel/debug:ro \
-e BEYLA_OPEN_PORT=8080 \
-e OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318 \
grafana/beyla
# Kubernetes (Helm)
helm repo add grafana https://grafana.github.io/helm-charts
helm install beyla grafana/beyla \
--set discovery.services[0].open_port=8080 \
--set otelTraces.endpoint=http://tempo:4318
# beyla-config.yml
log_level: INFO
discovery:
services:
- name: my-app
open_port: 8080
# or by process name:
# exe_path: /usr/bin/myapp
# or by K8s pod metadata (auto-detected in K8s)
ebpf:
wakeup_len: 100 # batch size for events
track_request_headers: false # enable to capture HTTP headers (high cardinality risk)
high_request_volume: false # optimize for high-traffic services
# Distributed tracing output (OTLP)
otel_traces_export:
endpoint: http://tempo:4318 # HTTP OTLP endpoint
# Or gRPC:
# endpoint: tempo:4317
# protocol: grpc
# Metrics output (Prometheus)
prometheus_export:
port: 9090
path: /metrics
# Or metrics via OTLP
otel_metrics_export:
endpoint: http://prometheus-otlp:9090
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: beyla
namespace: monitoring
spec:
selector:
matchLabels:
app: beyla
template:
metadata:
labels:
app: beyla
spec:
hostPID: true # required for eBPF
serviceAccountName: beyla
containers:
- name: beyla
image: grafana/beyla:latest
securityContext:
privileged: true # or use specific capabilities
# Alternative (non-privileged):
# capabilities:
# add: [SYS_ADMIN, SYS_PTRACE, NET_ADMIN]
env:
- name: BEYLA_OPEN_PORT
value: "8080"
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://alloy:4318"
volumeMounts:
- name: sys-kernel-debug
mountPath: /sys/kernel/debug
readOnly: true
volumes:
- name: sys-kernel-debug
hostPath:
path: /sys/kernel/debug
apiVersion: v1
kind: ServiceAccount
metadata:
name: beyla
namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: beyla
rules:
- apiGroups: [""]
resources: [nodes, pods, services, endpoints, namespaces]
verbs: [get, list, watch]
| Variable | Description |
|---|---|
BEYLA_OPEN_PORT | Port(s) to instrument (e.g., 8080, 8080-8090) |
BEYLA_EXECUTABLE_NAME | Process name pattern to instrument |
OTEL_EXPORTER_OTLP_ENDPOINT | OTLP endpoint for traces and metrics |
OTEL_EXPORTER_OTLP_PROTOCOL | grpc or http/protobuf (default) |
OTEL_SERVICE_NAME | Override service name in spans |
BEYLA_LOG_LEVEL | DEBUG, INFO, WARN, ERROR |
BEYLA_PROMETHEUS_PORT | Port for Prometheus metrics scrape |
BEYLA_PROMETHEUS_PATH | Path for Prometheus metrics (default /metrics) |
# Using Alloy as the OTLP receiver
otel_traces_export:
endpoint: http://alloy:4318 # Alloy forwards to Grafana Cloud Tempo
otel_metrics_export:
endpoint: http://alloy:4318 # Alloy forwards to Grafana Cloud Prometheus
Via Alloy config:
otelcol.receiver.otlp "beyla" {
http { endpoint = "0.0.0.0:4318" }
output {
traces = [otelcol.exporter.otlp.grafana_cloud.input]
metrics = [otelcol.exporter.prometheus.local.input]
}
}
Critical for production — prevents HTTP path cardinality explosion:
routes:
patterns:
- /user/{id}
- /api/v1/resources/{resource_id}
ignored_patterns:
- /health
- /metrics
ignore_mode: traces # or: metrics, both
unmatched: heuristic # or: path, wildcard, low-cardinality
unmatched strategies: heuristic (replaces numeric IDs, best default), low-cardinality (threshold-based collapsing), wildcard (/**), path (actual path — risk of explosion).
otel_traces_export:
sampler:
name: "parentbased_traceidratio" # parent-aware fraction sampling
arg: "0.1" # 10% sampling — arg is a quoted string
Samplers: always_on, always_off, traceidratio, parentbased_always_on (default), parentbased_traceidratio.
| Metric | Type | Description |
|---|---|---|
http.server.request.duration | Histogram | Inbound HTTP request duration |
http.client.request.duration | Histogram | Outbound HTTP request duration |
rpc.server.duration | Histogram | gRPC server call duration |
rpc.client.duration | Histogram | gRPC client call duration |
db.client.operation.duration | Histogram | DB query duration |
Labels: http.method, http.route, http.response.status_code, service.name, service.namespace
In Kubernetes, Beyla auto-discovers pods and enriches telemetry with K8s metadata:
discovery:
services:
- k8s_namespace: "production" # instrument all pods in namespace
- k8s_pod_name: "frontend.*" # by pod name regex
- k8s_deployment_name: "api" # by deployment name
- open_port: 8080 # or by port (any pod)
Auto-enriched span attributes: k8s.namespace.name, k8s.pod.name, k8s.node.name, k8s.deployment.name