Skip to main content

Telemetry

True Life includes a full observability stack with OpenTelemetry integration, providing distributed tracing, structured logging, and metrics.

Architecture

Flow: Web UI logs/spans → NUI fetch → FiveM Client → RPC → Server → OTLP HTTP → OTEL Collector → Tempo (traces) / Loki (logs) → Grafana

Server Configuration

Configure via convars in server.cfg:

set otel_enabled "true"
set otel_endpoint "http://localhost:4318"
set otel_service_name "true_life"

Pipeline Initialization

Server

// src/runtime/server/main.ts
import { initServerTelemetry, shutdownServerTelemetry } from "@core/telemetry/server";
 
// During bootstrap
initServerTelemetry({
	serviceName: "true_life",
	flushIntervalMs: 5000,
});
 
// During shutdown
await shutdownServerTelemetry();

Client

// src/runtime/client/main.ts
import { initClientTelemetry, shutdownClientTelemetry } from "@core/telemetry/client";
 
// During bootstrap
initClientTelemetry({
	flushIntervalMs: 2000,
});
 
// During shutdown
await shutdownClientTelemetry();

Web UI

// ui/src/main.tsx
import { initTelemetryForwarder, shutdownTelemetryForwarder } from "@ui/lib/telemetry";
 
// During app initialization
initTelemetryForwarder({
	flushIntervalMs: 1000,
});
 
// On app unmount
await shutdownTelemetryForwarder();

Observability Stack

The infra/ directory contains the full-stack configuration:

infra/
├── otel/                    # OpenTelemetry Collector
│   └── otel-collector-config.yaml
├── tempo/                   # Tempo (distributed tracing)
├── loki/                    # Loki (log aggregation)
├── grafana/                 # Grafana (visualization)
│   └── provisioning/
│       └── dashboards/      # Pre-configured dashboards
└── prometheus/              # Prometheus (metrics)

Starting the Stack

# Start full observability stack
docker compose up -d otel-collector tempo loki grafana prometheus
 
# Or just the essentials
docker compose up -d otel-collector tempo loki grafana

Accessing Services

ServiceURLDescription
Grafanahttp://localhost:3001Dashboards and visualization
Prometheushttp://localhost:9090Metrics queries
Tempohttp://localhost:3200Trace queries
Lokihttp://localhost:3100Log queries
OTEL Collectorhttp://localhost:4318OTLP HTTP receiver

Grafana Dashboards

Pre-configured dashboards are available:

  • Service Overview - Request rates, error rates, latencies
  • Trace Explorer - Search and visualize distributed traces
  • Log Explorer - Search structured logs with trace correlation
  • Player Metrics - Online players, resource usage

Exploring Traces

  1. Open Grafana at http://localhost:3001
  2. Go to Explore → Select Tempo data source
  3. Search by trace ID, service, or operation name
  4. Click on a trace to see the full span hierarchy

Log Correlation

Logs include trace context for correlation:

  1. Find a trace in Tempo
  2. Click "Logs for this trace" to see related logs in Loki
  3. Or search Loki with {traceId="..."} filter

OTEL Collector Configuration

The collector receives telemetry and routes it to backends:

# infra/otel/otel-collector-config.yaml
receivers:
    otlp:
        protocols:
            grpc:
                endpoint: 0.0.0.0:4317
            http:
                endpoint: 0.0.0.0:4318
 
processors:
    batch:
        timeout: 1s
        send_batch_size: 1024
 
exporters:
    otlp/tempo:
        endpoint: tempo:4317
        tls:
            insecure: true
    loki:
        endpoint: http://loki:3100/loki/api/v1/push
 
service:
    pipelines:
        traces:
            receivers: [otlp]
            processors: [batch]
            exporters: [otlp/tempo]
        logs:
            receivers: [otlp]
            processors: [batch]
            exporters: [loki]

Custom Metrics

Expose custom metrics via Prometheus:

// Custom counter example
import { incrementCounter, setGauge } from "@core/metrics";
 
// Increment a counter
incrementCounter("banking_transfers_total", { status: "success" });
 
// Set a gauge
setGauge("players_online", playerCount);

Best Practices

  1. Use spans for operations - Wrap significant operations
  2. Include relevant attributes - Player IDs, amounts, etc.
  3. Set appropriate log levels - Avoid noise
  4. Monitor error rates - Set up alerts in Grafana
  5. Sample high-volume traces - Reduce storage costs
  6. Correlate logs with traces - Use trace context