mirror of
https://github.com/XRPLF/rippled.git
synced 2026-08-21 22:30:57 +00:00
Six findings from the review of #6494 survived independent verification. Each was checked against the branch tip, and where behaviour was in question, against a live collector and Loki rather than from the reviewer's claim or from documentation alone. Plan-doc section numbering. 06-implementation-phases.md used "## 6.9" twice: for the new Phase 8 section and for the pre-existing Risk Assessment. Three references already pointed at 6.8.1 and none at 6.9, and the later phases are numbered 6.8.2 through 6.8.4, so Phase 8 becomes 6.8.1 and the sequence is monotonic. Renumbering to 6.10, as suggested on the PR, would have collided with Success Metrics. filelog read position. The receiver relied on the upstream default start_at=end, which skips everything a node wrote before the first poll and reads nothing at all from a log that has stopped being written to. Read from the beginning instead, paired with a file_storage extension so a restart resumes at the last offset rather than re-ingesting the file. The collector image runs as 10001:10001 and ships no writable directory, and a fresh named volume is root-owned, so a one-shot init service prepares the volume first. It reuses an image the stack already pulls, adding no new dependency. Loki log stream label. The job resource attribute did not become a Loki index label, so the documented {job="xrpld"} queries matched nothing. Verified against grafana/loki:3.4.2 with its default config: only service_name and deployment_environment are indexed, and job arrives as structured metadata, which a stream selector cannot match. Dropped the attribute and moved the twelve queries this branch introduced to {service_name="xrpld"}. Three further occurrences in 07-observability-backends.md originate on the phase-1a branch and are left for a commit there. Trace ids on unsampled spans. Logs::format emitted trace_id and span_id whenever the span context was valid. A span dropped by the ParentBasedSampler still carries its parent's ids, so log lines advertised traces that were never exported and the log-to-trace link resolved to nothing. Require the sampled flag as well, and correct the task list and the documentation that promised the fields unconditionally. The remaining two findings were refuted. The reported risk of signing material reaching Loki does not hold: Logs::format already scrubs seven sensitive fields, and there is a single write path to the log file, so every JLOG site is covered. The suggestion to add internalLink to the Loki derived field is not applicable, because that key is not part of Grafana's schema.
154 lines
5.8 KiB
YAML
154 lines
5.8 KiB
YAML
# Docker Compose stack for xrpld OpenTelemetry observability.
|
|
#
|
|
# Provides services for local development:
|
|
# - otel-collector: receives OTLP traces from xrpld, batches and
|
|
# forwards them to Tempo. Also tails xrpld log files
|
|
# via filelog receiver and exports to Loki. Listens on ports
|
|
# 4317 (gRPC) and 4318 (HTTP).
|
|
# - tempo: Grafana Tempo tracing backend, queryable via Grafana Explore
|
|
# on port 3000. Recommended for production (S3/GCS storage, TraceQL).
|
|
# - loki: Grafana Loki log aggregation backend for centralized log
|
|
# ingestion and log-trace correlation.
|
|
# - grafana: dashboards on port 3000, pre-configured with Tempo,
|
|
# Prometheus, and Loki datasources.
|
|
#
|
|
# Usage:
|
|
# docker compose -f docker/telemetry/docker-compose.yml up -d
|
|
#
|
|
# Configure xrpld to export traces by adding to xrpld.cfg:
|
|
# [telemetry]
|
|
# enabled=1
|
|
# endpoint=http://localhost:4318/v1/traces
|
|
|
|
services:
|
|
# One-shot init for the collector's offset store. Docker creates a fresh
|
|
# named volume owned by root, but the collector image runs as 10001:10001
|
|
# and ships no writable directory, so the file_storage extension could not
|
|
# create its database and the collector would fail to start. Chown the
|
|
# volume once, then exit; the collector waits for this to complete.
|
|
#
|
|
# Reuses the Prometheus image purely because the stack already pulls it and
|
|
# it has a shell — this adds no new image dependency. The entrypoint is
|
|
# overridden since that image normally starts the Prometheus server.
|
|
otelcol-storage-init:
|
|
image: prom/prometheus:v3.13.2
|
|
user: "0:0"
|
|
entrypoint: ["sh", "-c"]
|
|
command: ["mkdir -p /data/file_storage && chown -R 10001:10001 /data"]
|
|
volumes:
|
|
- otelcol-storage:/data
|
|
networks:
|
|
- xrpld-telemetry
|
|
|
|
# OpenTelemetry Collector: receives spans from xrpld via OTLP protocol,
|
|
# batches them for efficiency, and forwards to Tempo for storage.
|
|
otel-collector:
|
|
image: otel/opentelemetry-collector-contrib:0.158.0
|
|
command: ["--config=/etc/otel-collector-config.yaml"]
|
|
ports:
|
|
- "4317:4317" # OTLP gRPC
|
|
- "4318:4318" # OTLP HTTP (traces + native OTel metrics)
|
|
- "8889:8889" # Prometheus metrics (spanmetrics + OTLP)
|
|
# StatsD UDP port removed — beast::insight now uses native OTLP.
|
|
# Uncomment if using server=statsd fallback:
|
|
# - "8125:8125/udp"
|
|
volumes:
|
|
# Mount collector pipeline config (receivers → processors → exporters)
|
|
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml:ro
|
|
# Mount the xrpld log root for the filelog receiver. The telemetry
|
|
# configs write to docker/telemetry/data/logs/<network>/debug.log, so
|
|
# the default source is the repo-relative ./data/logs — user-owned and
|
|
# needing no root, so `docker compose up` works with no setup. Override
|
|
# XRPLD_LOG_DIR to point at another root (e.g. the integration test sets
|
|
# it to its own workdir). Mounted read-only so the collector only tails.
|
|
- ${XRPLD_LOG_DIR:-./data/logs}:/var/log/xrpld:ro
|
|
# Persisted filelog read offsets, so a collector restart resumes
|
|
# instead of re-reading every debug.log from the top.
|
|
- otelcol-storage:/var/lib/otelcol
|
|
depends_on:
|
|
tempo:
|
|
condition: service_started
|
|
loki:
|
|
condition: service_started
|
|
otelcol-storage-init:
|
|
condition: service_completed_successfully
|
|
networks:
|
|
- xrpld-telemetry
|
|
|
|
# Grafana Tempo: distributed tracing backend that stores and indexes
|
|
# spans. Queryable via TraceQL in Grafana Explore.
|
|
tempo:
|
|
image: grafana/tempo:2.9.4
|
|
command: ["-config.file=/etc/tempo.yaml"]
|
|
ports:
|
|
- "3200:3200" # Tempo HTTP API (health check, query)
|
|
volumes:
|
|
# Mount Tempo storage and ingestion config
|
|
- ./tempo.yaml:/etc/tempo.yaml:ro
|
|
# Persistent volume for trace data (WAL + blocks)
|
|
- tempo-data:/var/tempo
|
|
networks:
|
|
- xrpld-telemetry
|
|
|
|
# Grafana Loki for centralized log ingestion and log-trace
|
|
# correlation. Loki 3.x supports native OTLP ingestion, so the OTel
|
|
# Collector exports via otlphttp to Loki's /otlp endpoint.
|
|
# Query logs via Grafana Explore -> Loki at http://localhost:3000.
|
|
loki:
|
|
image: grafana/loki:3.4.2
|
|
ports:
|
|
- "3100:3100"
|
|
command: -config.file=/etc/loki/local-config.yaml
|
|
volumes:
|
|
- loki-data:/loki
|
|
networks:
|
|
- xrpld-telemetry
|
|
|
|
prometheus:
|
|
# Pinned to an exact patch release for reproducible, config-stable runs.
|
|
image: prom/prometheus:v3.13.2
|
|
ports:
|
|
- "9090:9090"
|
|
volumes:
|
|
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
|
- prometheus-data:/prometheus
|
|
depends_on:
|
|
- otel-collector
|
|
networks:
|
|
- xrpld-telemetry
|
|
|
|
# Grafana: visualization UI with Tempo pre-configured as a datasource.
|
|
# Anonymous admin access enabled for local development convenience.
|
|
grafana:
|
|
image: grafana/grafana:13.1.2
|
|
environment:
|
|
- GF_AUTH_ANONYMOUS_ENABLED=true # No login required for local dev
|
|
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin # Full access without auth
|
|
ports:
|
|
- "3000:3000" # Grafana web UI
|
|
volumes:
|
|
# Auto-provision Tempo datasource and search filters on startup
|
|
- ./grafana/provisioning:/etc/grafana/provisioning:ro
|
|
- ./grafana/dashboards:/var/lib/grafana/dashboards:ro
|
|
depends_on:
|
|
- tempo
|
|
- prometheus
|
|
- loki
|
|
networks:
|
|
- xrpld-telemetry
|
|
|
|
# Named volume for Tempo trace storage (WAL and compacted blocks).
|
|
# Data persists across container restarts. Remove with:
|
|
# docker compose -f docker/telemetry/docker-compose.yml down -v
|
|
volumes:
|
|
tempo-data:
|
|
prometheus-data:
|
|
loki-data:
|
|
otelcol-storage:
|
|
|
|
# Isolated bridge network so services communicate by container name
|
|
# (e.g., the collector reaches Tempo at http://tempo:4317).
|
|
networks:
|
|
xrpld-telemetry:
|
|
driver: bridge
|