Faro SDK sends traces (spans with events) via OTLP, not OTLP logs or
metrics. Rewrote all 3 Faro dashboards to use Tempo TraceQL queries
instead of Loki LogQL.
- faro-overview: page views, exceptions, console errors, navigation
- faro-js-errors: exception traces, console error traces
- faro-web-vitals: LCP, FCP, CLS, TTFB via web-vitals span events
All panels now query Tempo (uid P214B5B846CF3925F) with TraceQL.
- Fix OTel custom metrics not reaching Prometheus: ESM static import
hoisting caused metrics.getMeter() to run before sdk.start(), getting
NoopMeterProvider. Changed to lazy-init pattern so instruments are
created on first use after the SDK configures the real MeterProvider.
- Fix Grafana dashboards job labels: OTel adds service.namespace prefix
(job=farmafinder/farmafinder-backend), updated queries to use regex
match (job=~".*farmafinder-backend").
- Fix histogram metric names: OTel appends unit suffix (_milliseconds)
to histogram names (e.g. http_request_duration_ms_milliseconds_bucket).
Verified: app_heartbeat_total, http_requests_total, db_query_duration_ms,
redis_cmd_duration_ms, and all other custom metrics now flow correctly
through OTLP -> Alloy -> Prometheus remote_write.