Observability
Last updated April 25, 2026
Observe Matruno through OpenTelemetry, FastAPI instrumentation, SQL/Redis/HTTPX spans, Temporal metrics, browser RUM, PgBouncer metrics, Grafana assets, audits, and logs.
Implemented signal paths#
Matruno includes OpenTelemetry bootstrap for the backend and worker in backend/app/services/observability.py. It instruments FastAPI, SQLAlchemy, Redis, HTTPX, Python logging, custom business metrics, Temporal workflow/activity metrics, and PgBouncer exporter metrics.
Temporal instrumentation in backend/app/temporal/otel_instrumentation.py adds workflow, activity, task queue, workspace, workflow ID, and run ID metadata where available.
Collector and Grafana#
docker/otel-collector/config.yaml receives OTLP gRPC/HTTP and Docker stats, applies memory limits, resource attributes, tail-based trace sampling, batching, and exports traces, metrics, and logs to the configured Grafana Cloud OTLP endpoint.
The Grafana bundle in observability/grafana includes dashboard JSON, alert/rule YAML, and Terraform for dashboard/contact-point provisioning. It is a Grafana Cloud-oriented bundle, not proof that every deployment already has Grafana Cloud configured.
Browser RUM#
The frontend and admin panel include browser RUM libraries and same-origin OTLP proxy routes:
POST /api/observability/otlp/logs
POST /api/observability/otlp/metrics
POST /api/observability/otlp/traces
Browser observability is controlled by NEXT_PUBLIC_BROWSER_OBSERVABILITY_ENABLED, NEXT_PUBLIC_BROWSER_OTLP_BASE_URL, and OTEL_BROWSER_PROXY_TARGET.
Product-level signals#
The app also exposes usage summaries, daily usage charts, usage breakdowns, workflow usage metrics, matter timelines, audit logs, notification streams, webhook delivery records, external tool traces, and agent logs where the relevant features are used. Use these to reconstruct legal matter execution, not hidden model reasoning.
Local versus Grafana Cloud
Local Compose starts the collector, but Grafana Cloud export requires valid Grafana credentials. Without those credentials, use local logs, health endpoints, Temporal UI, and the app's own history surfaces.
Was this helpful?