# Grafana Beyla: eBPF instrumentation that is moving upstream to OBI

> Beyla attaches to running processes with eBPF to produce OpenTelemetry traces and RED metrics without touching application code. The repository is now a distribution point for upstream work under the name OBI.

**grafana/beyla** — eBPF-based autoinstrumentation of web applications and network metrics

- Repository: https://github.com/grafana/beyla
- Website: https://grafana.com/oss/beyla-ebpf/
- Stars: 2,137 · Forks: 203
- Language: Go
- License: Apache-2.0
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/grafana-beyla

## Why Grafana handed Beyla to the OpenTelemetry project

The first paragraph of the README is the most important thing in it, and it is not a feature list. Beyla has been donated to the CNCF OpenTelemetry Project under the name OpenTelemetry eBPF Instrumentation, shortened to OBI. Contributors are told that pull requests belong upstream unless they concern documentation, and that all current maintainers work full time on the upstream repository. The README says it expects the migration to finish shortly and that parts of the upstream codebase will likely arrive as a git submodule.

That reframes what this repository is. Grafana is no longer primarily the place the code is developed. It is the place the binary gets built and released for people who want Grafana's distribution of the tool. A reader deciding whether to adopt it should understand that they are adopting a project whose centre of gravity has already moved, and whose release cadence from here on depends on upstream.

The releases still come fast. Version 3.35.0 shipped on 2026-09-09, 3.36.0 on 2026-09-16 and 3.37.0 on 2026-09-23, and the last push was on 2026-09-28. Whatever the ownership arrangement means for the long term, the build is not sitting still.

## Running the example service and pointing Beyla at a port

Beyla needs something to instrument, so the getting started path is to fetch a small service from the repository's own examples directory and run it locally:

```bash
curl -OL https://raw.githubusercontent.com/grafana/beyla/main/examples/example-http-service/example-http-service.go
go run ./example-http-service.go
```

With the service up, the next step generates traffic so there is something to observe. This runs a request against the example every couple of seconds:

```bash
watch curl -s http://localhost:8080
```

Now the instrumenter runs. You download the release archive from the GitHub releases page, unpack it, and you get a single executable named beyla. The configuration is two environment variables and a privileged invocation:

```bash
export BEYLA_PROMETHEUS_PORT=9400
export BEYLA_OPEN_PORT=8080
sudo -E ./beyla
```

The first variable says where to expose metrics in Prometheus format, the second says which port holds the service you want watched. The `sudo -E` matters: the `-E` preserves the environment you just exported, and without elevated permissions the eBPF programs cannot attach. After that the metrics endpoint is live at `http://localhost:9400/metrics`, and that is the whole loop. You have not compiled an agent, linked a library or edited a config file.

## What the kernel probes actually capture

The mechanism is inspection rather than injection. The README describes eBPF as a way to automatically inspect application executables and the OS networking layer, which is how Beyla captures observability events for HTTP, HTTPS, HTTP2 and gRPC services without modifying application code or configuration. From those captured events it produces OpenTelemetry web transaction trace spans and Rate-Errors-Duration metrics.

Finding the right process is deliberately not a single mechanism. Beyla supports locating a service by network port, by executable name, or by process ID. That flexibility matters in containers, where port-based discovery is often the only stable handle, and it is one of the reasons the tool needs elevated privileges: it has to be able to see and attach to processes it did not start.

The exposition formats are not symmetric, and this is the detail most summaries skip. Distributed tracing is available for Go programs. Other languages get single span traces instead. So if you run a mixed estate, the trace fidelity you get depends on the language of the service, not on the configuration you write. Metrics, meanwhile, come out in Prometheus format or as OpenTelemetry metrics regardless of language.

Protocol coverage beyond HTTP is broader than the tracing story suggests. SQL, Redis, Kafka and MongoDB are all listed as supported instrumentations, which means a request can be described with its downstream database and queue calls attached.

## The kernel and language limits that decide where this runs

The requirements section is where a project like this becomes real, and it is more specific than the introduction suggests. Beyla needs Linux with kernel 5.8 or higher and BTF enabled, or one of the Red Hat Enterprise Linux 4.18 kernels from build 348 onward that carry the necessary backports, which covers CentOS, AlmaLinux and Oracle Linux. BTF became the default on most distributions at kernel 5.14. You can check your own kernel by looking for `/sys/kernel/btf/vmlinux`, and if you build your own kernel you need `CONFIG_DEBUG_INFO_BTF=y`.

There is a second limit specific to Go. Instrumented Go programs must have been compiled with at least Go 1.17, and the README says support covers Go applications built with a major version no earlier than three versions behind the current stable release. That is a moving window rather than a fixed promise, so a long lived deployment on an old toolchain can quietly fall outside it.

HTTPS coverage is narrower still. The README states that HTTPS instrumentation is limited to Go programs and to libraries or languages using libssl3, which covers a large part of the JVM and Python TLS stacks but not every runtime. The Go library list is explicit as well, naming `net/http`, Gorilla Mux, Gin, gRPC-Go, `x/net/http2`, Go-Redis v9, Sarama Kafka and kafka-Go. An HTTP framework that is not on that list is the most likely reason a given service produces no spans.

Permissions are the last gate. On a host you need sudo. On Kubernetes the repository points at `examples/k8s/unprivileged.yaml` for running with minimum capabilities, and for Docker Compose you need either a privileged container or the `SYS_ADMIN` capability granted explicitly.

## The vendored OBI module behind the build

The repository layout shows how far the migration has already gone. The tree contains a directory named `.obi-src`, and `go.mod` carries a replace directive pointing the OpenTelemetry instrumentation module at that local directory, with the comment explaining that it is included as a git submodule rather than downloaded. The module path itself is still `github.com/grafana/beyla/v3`, so the module major version tracks the tool, and the OpenTelemetry and Collector dependencies are pinned to recent versions.

The Makefile reads the replace directive out of `go.mod` at build time, which is why the submodule has to be present before anything compiles. The same file derives the release version from `git describe`, defaults the build to linux on amd64, and resolves the generator image used to build the eBPF binaries reproducibly. Two extra artifacts sit alongside the main executable: a Java agent, and a separate cache binary for Kubernetes metadata, each with its own entry point under `cmd/`.

The Dockerfile shows what the Java path costs. It builds a JNI native library using a Go image with a C cross compiler, cross-compiles for the other architecture, and then builds the Java agent from a Gradle JDK image before applying the Beyla specific patches on top of the upstream OBI source. Every base image is pinned by digest. This is a heavier build than a single static Go binary, and it is the practical price of covering the JVM without asking users to run a separate agent distribution.

For deployment, the tree carries `deployments/`, `charts/` and a `contrib/` directory, plus several `examples/` subdirectories covering a quickstart, an HTTP service, Kubernetes metadata caching and an Alloy configuration. Those are the paths to read when you need the operational shape rather than the getting started loop.

## What the README leaves to the documentation

The README is an advertisement with an accurate quick start attached, and a thin manual beyond that. It gives you the download, the two environment variables, the metrics URL, and a requirements list, then sends you to the Grafana documentation and the tutorials for everything else. Configuration beyond the two variables used here, the Kubernetes configuration, and the tuning of what gets collected are all documented off the repository page.

The honest comparison is against instrumenting by hand. Adding the OpenTelemetry SDK to a service gives precise control over which spans exist, what attributes they carry and what sampling costs you. Beyla gives you the same shape of output with none of that control, which is exactly why it needs kernel access and why it cannot see your business meaning. If you need a span attribute that says which tenant a request belonged to, neither the README nor the mechanism described here gets you there. Beyla wins on time to first dashboard, and loses on expressiveness.

Two operational notes are worth carrying into an evaluation. The community lives in the Grafana Slack in the #beyla channel, and there is a monthly call on the second Wednesday of the month at 4pm UTC, which is a sign of an active project rather than an abandoned one. And given the donation, the question to ask before adopting is not whether Beyla looks healthy today but whether the OBI name in `go.mod` and in the generator image path tells you where the project you are really tracking lives.

## Conclusion

Beyla is a good fit when you run Linux services and want request level telemetry without adding an SDK to each codebase, and a poor fit when you need custom business attributes, or your services run outside Linux kernels that expose BTF. The part worth understanding before you commit is the donation: the work now happens in the OpenTelemetry eBPF Instrumentation repository, so track releases there rather than assuming this one is frozen. Start with the example service on port 8080 and a Prometheus exposition on 9400, then read the vendoring notes to see how much of the code you would actually be reading.

## FAQ

### Does Beyla need any changes to my application code?

No. Beyla uses eBPF to inspect running executables and the OS networking layer, and the README states that data capture happens without modifications to your application code or configuration. You need Linux with BTF, eBPF enabled on the host, and elevated permissions to run the instrumenter.

### Which languages can Beyla produce distributed traces for?

Distributed tracing is documented for Go programs. Services in other languages get single span traces instead of full distributed traces, though metrics still come out in Prometheus or OpenTelemetry format regardless of language. HTTPS instrumentation is further limited to Go programs and to libraries or languages using libssl3.

### What has happened to Beyla now that it is called OBI?

Beyla was donated to the CNCF OpenTelemetry Project under the name OpenTelemetry eBPF Instrumentation, or OBI. New pull requests are expected upstream, the maintainers work there full time, and part of the upstream codebase is expected to arrive in this repository as a git submodule. Releases here continue, with 3.37.0 published on 2026-09-23.

## Sources

- [grafana/beyla on GitHub](https://github.com/grafana/beyla)
- [License: Apache-2.0](https://github.com/grafana/beyla/blob/main/LICENSE)
- [Project website](https://grafana.com/oss/beyla-ebpf/)
- [README](https://github.com/grafana/beyla/blob/main/README.md)
- [Releases](https://github.com/grafana/beyla/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/grafana-beyla
