Skip to content
Open
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
65 changes: 65 additions & 0 deletions observability-example/README.md
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a bit more info on the purpose of these tools. It's not obvious that this is mostly for local testing.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe rename the folder too? Alternatively, if we expect this folder to be filled with production telemetry tools in forked repos, we can somehow explain that.

Copy link
Contributor

@Ark-kun Ark-kun Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Folder is a bit too specific for the root dir.
Maybe something like
examples/setup/observability

Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Example observability stack (OTel Collector, Jaeger, Prometheus)

This directory runs an OpenTelemetry Collector, intended as an example or for testing new telemetry data. The collector receives telemetry from Tangle and forwards traces to Jaeger and metrics to Prometheus.

## Start the stack

From this directory:

```bash
docker-compose up -d
```

To view logs:

```bash
docker-compose logs -f
```

To stop:

```bash
docker-compose down
```

## Configure Tangle to export to the collector

Set these environment variables when running the Tangle API so it sends traces and metrics to the collector:

| Variable | Value | Description |
|----------|--------|-------------|
| `TANGLE_OTEL_EXPORTER_ENDPOINT` | `http://localhost:4317` | OTLP collector address (gRPC). Use `host.docker.internal:4317` if Tangle runs inside Docker. |
| `TANGLE_OTEL_EXPORTER_PROTOCOL` | `grpc` | Protocol for the exporter (default). This stack only accepts gRPC. |
| `TANGLE_ENV` | optional | Included in the service name (e.g. `tangle-development`). Default: `development`. |
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain what this is for? Is service name what is displayed/searched for in the observability tools?


Example (shell):

```bash
export TANGLE_OTEL_EXPORTER_ENDPOINT=http://localhost:4317
export TANGLE_OTEL_EXPORTER_PROTOCOL=grpc
# then start your Tangle API
```

Example (`.env` in the project root or where the API is started):

```
TANGLE_OTEL_EXPORTER_ENDPOINT=http://localhost:4317
TANGLE_OTEL_EXPORTER_PROTOCOL=grpc
```

If `TANGLE_OTEL_EXPORTER_ENDPOINT` is unset, tracing and metrics export are disabled.

## UIs

- **Jaeger** (traces): http://localhost:16686
- **Prometheus** (metrics): http://localhost:9090

## Ports

| Port | Service | Purpose |
|------|---------|---------|
| 4317 | OTel Collector | OTLP gRPC (ingest) |
| 9464 | OTel Collector | Prometheus scrape endpoint |
| 8888 | OTel Collector | Collector telemetry |
| 16686 | Jaeger | Web UI |
| 9090 | Prometheus | Web UI |
54 changes: 54 additions & 0 deletions observability-example/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Observability stack for Tangle: OpenTelemetry Collector, Jaeger (traces), Prometheus (metrics).
#
# Run from this directory: docker compose up -d
#
# Point the Tangle API at the collector so traces/metrics are exported:
# TANGLE_OTEL_EXPORTER_ENDPOINT=http://localhost:4317
# TANGLE_OTEL_EXPORTER_PROTOCOL=grpc
#
# UIs:
# Jaeger: http://localhost:16686
# Prometheus: http://localhost:9090

services:
otel-collector:
image: otel/opentelemetry-collector-contrib:latest
container_name: tangle-otel-collector
command: ["--config=/etc/otel-collector-config.yaml"]
volumes:
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml:ro
ports:
- "4317:4317" # OTLP gRPC
- "9464:9464" # Prometheus scrape (metrics from OTLP)
- "8888:8888" # Collector telemetry
depends_on:
- jaeger
restart: unless-stopped

jaeger:
image: jaegertracing/all-in-one:latest
container_name: tangle-jaeger
environment:
- COLLECTOR_OTLP_ENABLED=true
ports:
- "16686:16686" # Jaeger UI (traces)
restart: unless-stopped

prometheus:
image: prom/prometheus:latest
container_name: tangle-prometheus
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.path=/prometheus
- --web.enable-lifecycle
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus_data:/prometheus
ports:
- "9090:9090"
depends_on:
- otel-collector
restart: unless-stopped

volumes:
prometheus_data: {}
44 changes: 44 additions & 0 deletions observability-example/otel-collector-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# OpenTelemetry Collector config: receive OTLP, export traces to Jaeger and metrics for Prometheus scrape.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason why this file extension is .yaml, while the others are .yml?


receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317

processors:
batch: {}

exporters:
# Traces → Jaeger (OTLP gRPC)
otlp/jaeger:
endpoint: jaeger:4317
tls:
insecure: true

# Metrics → expose scrape endpoint for Prometheus
prometheus:
endpoint: "0.0.0.0:9464"
namespace: tangle

service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp/jaeger]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [prometheus]

telemetry:
logs:
level: info
metrics:
readers:
- pull:
exporter:
prometheus:
host: "0.0.0.0"
port: 8888
20 changes: 20 additions & 0 deletions observability-example/prometheus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Prometheus config: scrape OpenTelemetry Collector metrics and self.
global:
scrape_interval: 15s
evaluation_interval: 15s

scrape_configs:
# OpenTelemetry Collector metrics (app metrics sent via OTLP are exposed here for scrape)
- job_name: otel-collector
static_configs:
- targets: ["otel-collector:9464"]

# Collector's own telemetry
- job_name: otel-collector-telemetry
static_configs:
- targets: ["otel-collector:8888"]

# Prometheus self
- job_name: prometheus
static_configs:
- targets: ["localhost:9090"]