Generated banner for App Observability
Generated logo for App Observability

App Observability

Grafana LabsOfficialPublished by Grafana Labs

  • Skill
  • Tool integration
  • Cloud and DevOps
  • Apache-2.0
  • Low risk

From the author

Get RED metrics + service maps + frontend RUM + AI/LLM monitoring out of Grafana Cloud — Application Observability (`traces_spanmetrics_*` from OTel traces, p50/p95/p99 latency, exemplar-to-trace, traces-to-logs / profiles), Frontend Observability with the Faro Web SDK (Core Web Vitals, session replay, `pushError`, React + router integration, `TracingInstrumentation` for browser → backend trace correlation), and AI Observability via OpenLIT (token / cost / latency, GPU, hallucination + toxicity evals). Use when standing up APM for a service, wiring an Alloy OTLP receiver + forwarding to Cloud, instrumenting a React frontend for RUM, debugging why service-map edges are missing, monitoring LLM cost drift, or correlating a frontend error to its backend trace — even when the user says "set up APM", "show service map", "monitor browser perf", "session replay", "RUM SDK", or "watch our OpenAI bill" without naming App / Frontend / AI Observability.
— the description by Grafana Labs

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides a unified approach to monitoring modern software stacks using Grafana Cloud. It covers three core pillars: Application Observability for backend APM via OTel spanmetrics, Frontend Observability using the Faro Web SDK for RUM and session replay, and AI Observability via OpenLIT for monitoring LLM performance, costs, and model evaluations. The guide details the necessary plumbing, including Grafana Alloy configuration, OTel resource attribute requirements, and correlation strategies across metrics, logs, and traces.

What it does

  • Configures backend APM using OpenTelemetry and Grafana Alloy for RED metrics and service maps.
  • Implements frontend RUM and session replay using the Faro Web SDK with React integration.
  • Monitors LLM and GenAI applications for token usage, latency, costs, and hallucination evals via OpenLIT.
  • Establishes cross-signal correlation between frontend errors, backend traces, and logs.
  • Provides troubleshooting steps for missing service map edges and OTLP ingestion issues.
  • Offers standardized environment variable and resource attribute configurations for consistent observability.

When to use it

  • When setting up full-stack APM for a new or existing service.
  • When you need to monitor browser performance and user sessions in a web application.
  • When tracking LLM API costs, latency, and model quality in AI-powered applications.
  • When debugging missing service map edges or correlating frontend errors to backend traces.
  • When migrating to or configuring Grafana Cloud as your primary observability backend.

Advantages

  • Unified observability across frontend, backend, and AI components.
  • Leverages open standards like OpenTelemetry for vendor-agnostic instrumentation.
  • Reduces manual configuration through pre-built dashboards and auto-instrumentation.
  • Enables deep correlation between metrics, logs, traces, and profiles.
  • Provides clear paths for monitoring modern GenAI workloads alongside traditional services.

Usage examples

“How do I set up APM for my Node.js service to show up in Grafana Cloud?”
The agent provides the OTel SDK installation steps, the required resource attributes (service.name, service.namespace), and the Grafana Alloy configuration to forward traces to your Cloud instance.
“I need to monitor my OpenAI API usage and costs in Grafana.”
The agent guides you through installing OpenLIT, initializing it in your Python app, and configuring the OTLP exporter to send GenAI metrics to your Grafana Cloud instance.
“How can I link my React frontend errors to backend traces?”
The agent explains how to initialize the Faro Web SDK with TracingInstrumentation, ensuring the traceparent header is injected to correlate browser events with backend Tempo traces.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/grafana/app-observability/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip app-observability.zip -d .agents/skills

Documentation by Grafana Labs

Grafana Cloud Application Observability

Docs: https://grafana.com/docs/grafana-cloud/monitor-applications/

Three products that share the same OTLP + Mimir / Loki / Tempo / Pyroscope plumbing:

  1. Application Observability — APM from OTel spanmetrics

  2. Frontend Observability — Faro Web SDK, RUM + session replay

  3. AI Observability — LLM / vector-DB monitoring via OpenLIT

Prerequisites

  • Grafana Cloud stack + OTLP endpoint + numeric instance ID + API key with MetricsPublisher + LogsPublisher + TracesPublisher

  • For APM: app instrumented with OTel SDK; for Frontend: a web app + Faro app key; for AI: Python ≥ 3.10

  • Grafana Alloy as the local OTLP receiver (recommended)

Common Workflows

1. Stand up APM — Alloy receiver → Grafana Cloud + verify
# 1. Set Cloud creds + start Alloy with config from references/apm.md
export GRAFANA_CLOUD_OTLP_ENDPOINT=https://otlp-gateway-prod-us-east-0.grafana.net/otlp
export GRAFANA_CLOUD_INSTANCE_ID=123456
export GRAFANA_CLOUD_API_KEY=glc_eyJ...
alloy fmt /etc/alloy/config.alloy   # syntax check
alloy run /etc/alloy/config.alloy

# 2. Verify Alloy is receiving + forwarding
curl -s http://localhost:12345/api/v0/web/components \
  | jq '.[] | select(.id|test("otelcol\\.exporter\\.otlphttp"))
        | {id, health:.health.state}'
# Expect health.state == "healthy"
curl -s http://localhost:12345/metrics \
  | grep -E 'otelcol_(receiver_accepted_spans|exporter_sent_spans)'

# 3. Point your app at Alloy (with required attributes!)
export OTEL_SERVICE_NAME="my-api"
export OTEL_RESOURCE_ATTRIBUTES="service.namespace=myteam,deployment.environment=production"
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
export OTEL_EXPORTER_OTLP_PROTOCOL=grpc

# 4. Verify spans landed in Tempo + spanmetrics generated
#    Tempo (TraceQL):  { resource.service.name = "my-api" }
#    Mimir (PromQL):   sum by (job) (rate(traces_spanmetrics_calls_total{service_name="my-api"}[5m]))
#    Expect > 0 within ~1 minute.

# 5. Verify it's wired to App Observability
#    Grafana → Application → Service Inventory: "my-api" should appear with RED metrics
#    Click into it → Service Map edges visible (requires span.kind on outbound calls)

Full Alloy block + required resource attributes + spanmetric names + correlation links: references/apm.md.

2. Instrument a React frontend with Faro
# 1. Install
npm install @grafana/faro-react @grafana/faro-web-tracing
// 2. initializeFaro with TracingInstrumentation + ReactIntegration (see references/faro.md)
//    Push a smoketest event so we have a known signal:
faro.api.pushEvent('faro_smoketest', { ts: Date.now().toString() });
# 3. Verify in DevTools Network — POST to /collect returns 202
#    (401 → wrong app key; 404 → wrong url region)

# 4. Verify in Grafana Cloud
#    - Frontend Observability → your app → Sessions: your session appears
#    - LogQL on Loki: {kind="event"} |= "faro_smoketest"
#    - With TracingInstrumentation: open the session → the trace ID links to Tempo

Full React example, CDN setup, session config: references/faro.md.

3. Add AI / LLM observability
pip install openlit==1.42.0
# At app startup
import openlit
openlit.init(application_name="my-ai-app", environment="production")
# Your existing OpenAI / Anthropic / Cohere calls now emit OTel spans + metrics.
# Env (same OTLP endpoint as APM)
export OTEL_SERVICE_NAME="my-ai-app"
export OTEL_EXPORTER_OTLP_ENDPOINT="https://otlp-gateway-<region>.grafana.net/otlp"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Basic $(echo -n $ID:$KEY | base64)"

# Verify after a few LLM calls:
#   PromQL: sum by (gen_ai_request_model) (rate(gen_ai_usage_input_tokens_total[5m]))
#   Dashboard: Grafana → AI Observability → "GenAI Observability" auto-populates

Full OpenLIT install, evals/guards, GenAI metric list, dashboard names: references/ai-observability.md.

Full-stack correlation cheat sheet

SignalProductStorageQuery
RED metricsApp ObservabilityMimirPromQL
TracesTempoTempoTraceQL
LogsLokiLokiLogQL
ProfilesPyroscopePyroscopeProfileQL
Browser RUMFrontend ObservabilityLoki + TempoLogQL / TraceQL
LLM metricsAI ObservabilityMimirPromQL

Correlation keys: service.name joins all signals; trace exemplars embed trace IDs in metric points; traceID in logs and traceparent injected by Faro for FE → BE linking.

Troubleshooting

  • Service missing from Service Inventory → missing service.namespace (job label) or deployment.environment resource attribute

  • Service Map edges missing → span.kind not set on outbound calls (must be CLIENT) or inbound (SERVER)

  • Faro /collect returns 401 → wrong app key; 404 → region in URL doesn't match the Faro app

  • No GenAI metrics → confirm OpenLIT version matches OTel semantic-conv version expected by Cloud; verify auth with curl as in workflow #3

References

Resources

Files

references/faro.md

Frontend Observability (Faro)

SDK packages

@grafana/faro-core          # core API + transports
@grafana/faro-web-sdk       # web instrumentations + transports
@grafana/faro-web-tracing   # OpenTelemetry-JS distributed tracing
@grafana/faro-react         # React error boundary + router integration

Basic web setup (npm)

npm install @grafana/faro-web-sdk
import { initializeFaro, getWebInstrumentations } from '@grafana/faro-web-sdk';

const faro = initializeFaro({
  url: 'https://faro-collector-prod-<region>.grafana.net/collect/<app-key>',
  app: { name: 'my-frontend-app', version: '1.0.0', environment: 'production' },
  instrumentations: [
    ...getWebInstrumentations({ captureConsole: true }),
  ],
});

faro.api.pushLog(['User clicked checkout']);
faro.api.pushError(new Error('Payment failed'));
faro.api.pushEvent('button_click', { button: 'checkout' });

CDN setup

<script src="https://unpkg.com/@grafana/faro-web-sdk@latest/dist/library/faro-web-sdk.iife.js"></script>
<script>
  const { initializeFaro, getWebInstrumentations } = GrafanaFaroWebSdk;
  initializeFaro({
    url: 'https://faro-collector-prod-<region>.grafana.net/collect/<app-key>',
    app: { name: 'my-app', version: '1.0.0' },
    instrumentations: [...getWebInstrumentations()],
  });
</script>

React + tracing

npm install @grafana/faro-react @grafana/faro-web-tracing
import { initializeFaro, getWebInstrumentations } from '@grafana/faro-web-sdk';
import { TracingInstrumentation }               from '@grafana/faro-web-tracing';
import { createReactRouterV6DataOptions, ReactIntegration,
         withFaroRouterInstrumentation }        from '@grafana/faro-react';
import { createBrowserRouter, RouterProvider }  from 'react-router-dom';

initializeFaro({
  url: 'https://faro-collector-prod-<region>.grafana.net/collect/<app-key>',
  app: { name: 'my-react-app', version: '1.0.0', environment: 'production' },
  instrumentations: [
    ...getWebInstrumentations({ captureConsole: true }),
    new TracingInstrumentation(),
    new ReactIntegration({ router: createReactRouterV6DataOptions({}) }),
  ],
});

const router = withFaroRouterInstrumentation(createBrowserRouter([
  { path: '/',      element: <Home />  },
  { path: '/about', element: <About /> },
]));

Session config

initializeFaro({
  url: '...', app: { name: 'my-app' },
  sessionTracking: {
    enabled: true,
    persistent: true,
    maxSessionPersistenceTime: 4 * 60 * 60 * 1000, // 4 hours
    samplingRate: 1,  // 1 = 100%
    onSessionChange: (oldS, newS) => console.log('session', newS.id),
  },
  instrumentations: [...getWebInstrumentations()],
});

Where to find the collector URL

Grafana Cloud → Connections → search "Frontend Observability" → click → Web SDK Configuration tab → copy the url.

Auto-captured signals

  • Page views + navigation timing

  • Core Web Vitals (LCP, CLS, INP — INP replaces FID in Faro v2)

  • JS errors + unhandled rejections

  • Console errors / warnings (when captureConsole: true)

  • Resource loading performance

  • User interactions (clicks, form events)

  • Fetch / XHR timing

  • With TracingInstrumentation: traceparent header injection → backend trace correlation

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs network access, Needs an API key, Needs Python, Needs Node.js

Security

What our scanner noticed· Low risk

  • Instructions that use the network

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
Grafana Labs
Publisher
Grafana Labs (Official)
Source
grafana/skills · skills/grafana-cloud/app-observability · commit 8fb72a5
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Grafana Labs or Grafana Labs.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download app-observability.zip