Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
* text=auto
mvnw eol=lf
*.sh eol=lf
*.cs eol=crlf
Dockerfile eol=lf
38 changes: 38 additions & 0 deletions .github/renovate-tracked-deps.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
},
"docker/Dockerfile": {
"dockerfile": [
"docker.io/otel/ebpf-instrument",
"docker.io/redhat/ubi9",
"docker.io/redhat/ubi9-micro"
],
"regex": [
"cosign",
"grafana",
"loki",
"obi",
"opentelemetry-collector",
"prometheus",
"pyroscope",
Expand Down Expand Up @@ -169,6 +171,42 @@
"express"
]
},
"examples/obi/dotnet/Dockerfile": {
"dockerfile": [
"mcr.microsoft.com/dotnet/aspnet",
"mcr.microsoft.com/dotnet/sdk"
]
},
"examples/obi/generate-traffic.Dockerfile": {
"dockerfile": [
"ubuntu"
]
},
"examples/obi/go/Dockerfile": {
"dockerfile": [
"golang"
]
},
"examples/obi/go/go.mod": {
"gomod": [
"go"
]
},
"examples/obi/java.Dockerfile": {
"dockerfile": [
"eclipse-temurin"
]
},
"examples/obi/nodejs/Dockerfile": {
"dockerfile": [
"node"
]
},
"examples/obi/nodejs/package.json": {
"npm": [
"express"
]
},
"examples/python/Dockerfile": {
"regex": [
"opentelemetry-distro"
Expand Down
2 changes: 1 addition & 1 deletion .github/renovate.json5
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
ignoreUnstable: false,
},
{
matchPackageNames: ["grafana/grafana", "grafana/loki", "grafana/pyroscope", "grafana/tempo", "open-telemetry/opentelemetry-collector-releases", "prometheus/prometheus"],
matchPackageNames: ["otel/ebpf-instrument", "grafana/grafana", "grafana/loki", "grafana/pyroscope", "grafana/tempo", "open-telemetry/opentelemetry-collector-releases", "prometheus/prometheus"],
labels: ["docker-dependency"],
},
{
Expand Down
58 changes: 58 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,66 @@ You can enable logging in the .env file for troubleshooting:
| `ENABLE_LOGS_TEMPO` | Tempo |
| `ENABLE_LOGS_PYROSCOPE` | Pyroscope |
| `ENABLE_LOGS_OTELCOL` | OpenTelemetry Collector |
| `ENABLE_LOGS_OBI` | OBI |
| `ENABLE_LOGS_ALL` | All of the above |

This has nothing to do with any application logs, which are collected by OpenTelemetry.

### Enable OBI (eBPF auto-instrumentation)

[OpenTelemetry eBPF Instrumentation (OBI)][obi] uses eBPF to automatically generate traces and
[RED][red-method] metrics for HTTP/gRPC services — with zero code changes.

To enable OBI, add `ENABLE_OBI=true` to your `.env` file or pass it as an
environment variable:

```sh
ENABLE_OBI=true ./run-lgtm.sh

# Using mise
mise run lgtm-obi
```

**Requirements:** Linux kernel 5.8+ with BTF support. The `run-lgtm.sh` and
`run-lgtm.ps1` scripts automatically add the required `--pid=host` and
`--privileged` Docker flags when OBI is enabled. If you run `docker run`
directly, you must add these flags manually.

> [!NOTE]
> The `--pid=host` flag shares the host's PID namespace with the container,
> so OBI can discover and instrument processes running on the host — not just
> inside the container. For example, `OBI_TARGET=java` will instrument Java
> processes running on the host as well.

#### Target specific applications

By default, OBI discovers services on common ports (80, 443, 8080-8099,
3000-3999, 5000-5999). You can target specific applications:

```sh
# Monitor all Java processes
ENABLE_OBI=true OBI_TARGET=java ./run-lgtm.sh

# Monitor all Python processes
ENABLE_OBI=true OBI_TARGET=python ./run-lgtm.sh

# Monitor a specific executable by name
ENABLE_OBI=true OBI_TARGET=myapp ./run-lgtm.sh

# Monitor specific ports
ENABLE_OBI=true OTEL_EBPF_OPEN_PORT=8080,9090 ./run-lgtm.sh
```

<!-- editorconfig-checker-disable -->
Comment thread
martincostello marked this conversation as resolved.

| Variable | Purpose |
|-----------------------------|-------------------------------------------------------------------------------------------------|
| `OBI_TARGET` | Friendly language target: `java`, `python`, `node`, `dotnet`, `ruby`, or any regular expression |
| `OTEL_EBPF_OPEN_PORT` | Override ports to monitor (native OBI environment variable) |
| `OTEL_EBPF_AUTO_TARGET_EXE` | Executable name pattern (native OBI environment variable, set automatically by `OBI_TARGET`) |

<!-- editorconfig-checker-enable -->

### Send data to vendors

In addition to the built-in observability tools, you can also send data to vendors.
Expand Down Expand Up @@ -246,6 +302,7 @@ cosign verify ${IMAGE} --certificate-identity ${IDENTITY} --certificate-oidc-iss
<!-- markdownlint-disable MD013 -->

[app-o11y]: https://grafana.com/products/cloud/application-observability/
[obi]: https://opentelemetry.io/docs/zero-code/obi/ "OpenTelemetry eBPF Instrumentation"
[cosign]: https://github.com/sigstore/cosign "Cosign on GitHub"
[docker-hub]: https://hub.docker.com/r/grafana/otel-lgtm
[docker-latest]: https://img.shields.io/docker/v/grafana/otel-lgtm?logo=docker&label=latest&color=blue
Expand All @@ -262,3 +319,4 @@ cosign verify ${IMAGE} --certificate-identity ${IDENTITY} --certificate-oidc-iss
[otlp-endpoint]: https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/#otel_exporter_otlp_endpoint
[otlp-headers]: https://opentelemetry.io/docs/languages/sdk-configuration/otlp-exporter/#otel_exporter_otlp_headers
[oats]: https://github.com/grafana/oats
[red-method]: https://grafana.com/blog/the-red-method-how-to-instrument-your-services/ "The RED Method"
11 changes: 11 additions & 0 deletions docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ ARG LOKI_VERSION=v3.6.5
ARG PYROSCOPE_VERSION=v1.18.0
# renovate: datasource=github-releases depName=opentelemetry-collector packageName=open-telemetry/opentelemetry-collector-releases
ARG OPENTELEMETRY_COLLECTOR_VERSION=v0.145.0
# renovate: datasource=docker depName=obi packageName=otel/ebpf-instrument
ARG OBI_VERSION=v0.4.1

# hadolint global ignore=DL3059
FROM docker.io/otel/ebpf-instrument:${OBI_VERSION} AS obi-source

FROM docker.io/redhat/ubi9:9.7@sha256:b8923f58ef6aebe2b8f543f8f6c5af15c6f9aeeef34ba332f33bf7610012de0c AS builder

RUN mkdir /otel-lgtm
Expand All @@ -30,6 +34,8 @@ COPY prometheus.yaml \
run-tempo.sh \
pyroscope-config.yaml \
run-pyroscope.sh \
obi-config.yaml \
run-obi.sh \
otelcol-config*.yaml \
run-otelcol.sh \
run-all.sh \
Expand Down Expand Up @@ -82,6 +88,9 @@ RUN ./download-loki.sh $LOKI_VERSION
RUN ./download-pyroscope.sh $PYROSCOPE_VERSION
RUN ./download-otelcol.sh $OPENTELEMETRY_COLLECTOR_VERSION

COPY --from=obi-source /ebpf-instrument /otel-lgtm/obi/obi
COPY --from=obi-source /obi-java-agent.jar /otel-lgtm/obi/obi-java-agent.jar

COPY grafana-datasources.yaml /otel-lgtm/grafana/conf/provisioning/datasources/
COPY grafana-dashboards.yaml /otel-lgtm/grafana/conf/provisioning/dashboards/

Expand All @@ -103,13 +112,15 @@ ARG PROMETHEUS_VERSION
ARG TEMPO_VERSION
ARG LOKI_VERSION
ARG PYROSCOPE_VERSION
ARG OBI_VERSION
ARG OPENTELEMETRY_COLLECTOR_VERSION
ENV LGTM_VERSION=${LGTM_VERSION}
ENV GRAFANA_VERSION=${GRAFANA_VERSION}
ENV PROMETHEUS_VERSION=${PROMETHEUS_VERSION}
ENV TEMPO_VERSION=${TEMPO_VERSION}
ENV LOKI_VERSION=${LOKI_VERSION}
ENV PYROSCOPE_VERSION=${PYROSCOPE_VERSION}
ENV OBI_VERSION=${OBI_VERSION}
ENV OPENTELEMETRY_COLLECTOR_VERSION=${OPENTELEMETRY_COLLECTOR_VERSION}

# Re-label the final image, overriding any existing labels from the base image
Expand Down
12 changes: 12 additions & 0 deletions docker/obi-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
ebpf:
context_propagation: all

otel_traces_export:
Comment thread
zeitlinger marked this conversation as resolved.
endpoint: http://127.0.0.1:4318

otel_metrics_export:
endpoint: http://127.0.0.1:4318

prometheus_export:
port: 6060
path: /metrics
26 changes: 26 additions & 0 deletions docker/run-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ start_component "tempo"
start_component "pyroscope"
./run-pyroscope.sh &

if [[ ${ENABLE_OBI:-false} == "true" ]]; then
start_component "obi"
./run-obi.sh &
fi

echo "Waiting for the OpenTelemetry collector and the Grafana LGTM stack to start up..."

# Declare arrays to store service status and elapsed times
Expand Down Expand Up @@ -118,11 +123,32 @@ echo "Prometheus: ${elapsed_times[prometheus]} seconds"
echo "Tempo: ${elapsed_times[tempo]} seconds"
echo "Pyroscope: ${elapsed_times[pyroscope]} seconds"
echo "OpenTelemetry collector: ${elapsed_times[otelcol]} seconds"
if [[ ${ENABLE_OBI:-false} == "true" ]]; then
echo "OBI: (opt-in, not in health check)"
fi
echo "Total: ${total_elapsed} seconds"

touch /tmp/ready
echo "The OpenTelemetry collector and the Grafana LGTM stack are up and running. (created /tmp/ready)"

if [[ ${ENABLE_OBI:-false} == "true" ]]; then
# Non-blocking check — don't delay readiness if OBI fails (e.g. missing capabilities)
if curl -o /dev/null -sg "http://127.0.0.1:6060/metrics" -w "%{response_code}" 2>/dev/null | grep -q "200"; then
echo "OBI is up and running."
else
echo "Warning: OBI internal metrics endpoint is not responding. This may indicate missing eBPF capabilities (--pid=host --privileged)."
fi
if [[ -n ${OBI_TARGET:-} ]]; then
echo "OBI: monitoring '${OBI_TARGET}' processes"
elif [[ -n ${OTEL_EBPF_AUTO_TARGET_EXE:-} ]]; then
echo "OBI: monitoring processes matching executable name '${OTEL_EBPF_AUTO_TARGET_EXE}'"
elif [[ -n ${OTEL_EBPF_OPEN_PORT:-} ]]; then
echo "OBI: monitoring processes on ports ${OTEL_EBPF_OPEN_PORT}"
else
echo "OBI: monitoring processes on default open ports (80, 443, 8080-8099, 3000-3999, 5000-5999)"
fi
fi

echo "Open ports:"
echo " - 4317: OpenTelemetry GRPC endpoint"
echo " - 4318: OpenTelemetry HTTP endpoint"
Expand Down
22 changes: 22 additions & 0 deletions docker/run-obi.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash

source ./logging.sh
Comment thread
zeitlinger marked this conversation as resolved.

# Map friendly language names to OBI's OTEL_EBPF_AUTO_TARGET_EXE
case "${OBI_TARGET:-}" in
java) export OTEL_EBPF_AUTO_TARGET_EXE="java" ;;
python) export OTEL_EBPF_AUTO_TARGET_EXE="python|python3" ;;
node) export OTEL_EBPF_AUTO_TARGET_EXE="node" ;;
dotnet) export OTEL_EBPF_AUTO_TARGET_EXE="dotnet" ;;
ruby) export OTEL_EBPF_AUTO_TARGET_EXE="ruby" ;;
go) echo "Note: Go binaries have no common executable name. Use OTEL_EBPF_OPEN_PORT or OTEL_EBPF_AUTO_TARGET_EXE with your binary name." ;;
"") ;; # use default port-based discovery (see below)
*) export OTEL_EBPF_AUTO_TARGET_EXE="${OBI_TARGET}" ;; # pass through as regex
esac

# Default to port-based discovery when no specific target or port is configured
if [[ -z ${OTEL_EBPF_AUTO_TARGET_EXE:-} && -z ${OTEL_EBPF_OPEN_PORT:-} ]]; then
export OTEL_EBPF_OPEN_PORT="80,443,8080-8099,3000-3999,5000-5999"
fi

run_with_logging "OBI ${OBI_VERSION}" "${ENABLE_LOGS_OBI:-false}" ./obi/obi --config=./obi-config.yaml
Loading