mirror of
https://github.com/XRPLF/rippled.git
synced 2026-09-27 15:28:03 +00:00
The three tracker files conflicted because both sides had rewritten them. Took the incoming lock-free class, then put this branch's two monotonic accessors back on top of it: totalAgreementsEver() and totalMissedEver(), backed by a gross pair incremented at first classification and left alone by the repair branch. MetricsRegistry reads both, so dropping them would not compile. The test file kept the incoming suite, which renames every case, and gained this branch's two gross-counter cases adapted to the injected clock.
234 lines
9.9 KiB
YAML
234 lines
9.9 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 file_log 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.
|
|
#
|
|
# Requires Docker Compose >= 2.24.0. The grafana service uses the long-form
|
|
# `env_file` mapping (`path:` / `required:`), which older Compose cannot parse —
|
|
# and it fails for the whole file, not just that service. The long form is
|
|
# needed: `.env.alerting` is gitignored and absent in a fresh clone, and the
|
|
# short form treats a missing env file as an error.
|
|
#
|
|
# Usage:
|
|
# docker compose -f docker/telemetry/docker-compose.yml up -d
|
|
#
|
|
# Configure xrpld to export traces by adding to xrpld.cfg:
|
|
# [telemetry]
|
|
# enabled=1
|
|
# traces_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
|
|
|
|
# One-shot init for the xrpld log root. Docker creates a missing bind-mount
|
|
# source as root, and xrpld then cannot create the <network> subdirectory
|
|
# inside it. Config::getDebugLogFile() only warns on that failure and carries
|
|
# on, so the node looks healthy while writing no debug.log at all and the
|
|
# whole log pipeline stays empty with no error at any layer. Create the
|
|
# directory here and hand it to the host user instead.
|
|
#
|
|
# XRPLD_UID/XRPLD_GID default to 1000, the first non-root user on a typical
|
|
# Linux host. Set them if `id -u` differs, or xrpld still cannot write.
|
|
# Reuses the Prometheus image for the same reason otelcol-storage-init does.
|
|
xrpld-logdir-init:
|
|
image: prom/prometheus:v3.13.2
|
|
user: "0:0"
|
|
entrypoint: ["sh", "-c"]
|
|
command:
|
|
[
|
|
"mkdir -p /data/logs && chown ${XRPLD_UID:-1000}:${XRPLD_GID:-1000} /data /data/logs",
|
|
]
|
|
volumes:
|
|
- ./data:/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
|
|
# Second --config layers file_log offset persistence on top of the shared
|
|
# base config; the collector deep-merges them. Only this stack keeps its
|
|
# logs across restarts, so only this stack needs it.
|
|
command:
|
|
[
|
|
"--config=/etc/otel-collector-config.yaml",
|
|
"--config=/etc/otel-collector-filestorage.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
|
|
# Dev-only overlay: persist file_log read offsets across restarts
|
|
- ./otel-collector-filestorage.yaml:/etc/otel-collector-filestorage.yaml:ro
|
|
# Mount the xrpld log root for the file_log receiver. The telemetry
|
|
# configs write to docker/telemetry/data/logs/<network>/debug.log, so
|
|
# the default source is the repo-relative ./data/logs, which
|
|
# xrpld-logdir-init has already created and handed to the host user.
|
|
# Override XRPLD_LOG_DIR to point at another root (e.g. the integration
|
|
# test sets it to its own workdir; that root is created by the test, so
|
|
# the init service is a no-op there). Mounted read-only so the collector
|
|
# only tails.
|
|
- ${XRPLD_LOG_DIR:-./data/logs}:/var/log/xrpld:ro
|
|
# Persisted file_log 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
|
|
xrpld-logdir-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 otlp_http to Loki's /otlp endpoint.
|
|
# Query logs via Grafana Explore -> Loki at http://localhost:3000.
|
|
loki:
|
|
image: grafana/loki:3.7.6
|
|
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
|
|
# Alerting secrets/addresses (Slack webhook, alert email) come from this
|
|
# gitignored file; Grafana expands the ${VARS} referenced in the alerting
|
|
# provisioning YAML. Absent file = unset vars = receivers have no live
|
|
# destination, which is fine for a local stack. See .env.alerting.example.
|
|
env_file:
|
|
- path: .env.alerting
|
|
required: false
|
|
environment:
|
|
- GF_AUTH_ANONYMOUS_ENABLED=true # No login required for local dev
|
|
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin # Full access without auth
|
|
# Remote image rendering: point Grafana at the renderer container.
|
|
# These belong on the grafana service (the server delegates renders);
|
|
# the callback URL is how the renderer fetches the panel from grafana.
|
|
- GF_RENDERING_SERVER_URL=http://renderer:8081/render
|
|
- GF_RENDERING_CALLBACK_URL=http://grafana:3000/
|
|
# Grafana 13 turns the renderAuthJWT feature toggle on by default, which
|
|
# makes the renderer reject requests unless both sides share a token that
|
|
# is not the "-" default. Must match AUTH_TOKEN on the renderer service.
|
|
- GF_RENDERING_RENDERER_TOKEN=${GF_RENDERING_RENDERER_TOKEN:-xrpld-local-render}
|
|
# SMTP for the critical-tier email receiver and the Slack webhook / email
|
|
# address for the contact points all come from the env_file above, which
|
|
# injects them straight into the container environment for Grafana to
|
|
# expand. They are deliberately NOT duplicated here: a compose-level
|
|
# `environment:` entry is interpolated from the host shell and would
|
|
# override (and blank out) the env_file values.
|
|
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
|
|
- renderer
|
|
networks:
|
|
- xrpld-telemetry
|
|
|
|
# Grafana image renderer: a sidecar that renders panels/dashboards to PNG
|
|
# for image export and alerting. Grafana calls it at http://renderer:8081.
|
|
renderer:
|
|
# Pinned like every other image in this stack so a stack that worked
|
|
# yesterday still works today. Upstream maintains only the newest release,
|
|
# which is expected to serve all supported Grafana versions.
|
|
image: grafana/grafana-image-renderer:v5.12.0
|
|
environment:
|
|
# Shared secret for the JWT-authenticated render requests Grafana 13
|
|
# sends. Must match GF_RENDERING_RENDERER_TOKEN on the grafana service.
|
|
- AUTH_TOKEN=${GF_RENDERING_RENDERER_TOKEN:-xrpld-local-render}
|
|
ports:
|
|
- "8081:8081" # Renderer HTTP endpoint (called by grafana)
|
|
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
|