agentsclimarketplace

Grafana

Skill roderik/fold/skills/grafana

Query and investigate Grafana observability data (Loki logs, Prometheus metrics, Tempo traces). Use this skill whenever the user mentions Grafana, asks about logs, metrics, traces, pod restarts, alerts, error rates, latency, OOM kills, crash loops, monitoring, observability, debugging production issues, or investigating any Kubernetes/infrastructure problem. Also triggers on alert messages pasted from Grafana or Slack (e.g. "[FIRING:N]"), or when the user wants to check dashboards, query Loki/Prometheus/Tempo, or correlate observability signals.From its SKILL.md

Install
npx -y skills add roderik/fold --skill grafana

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

7.7 KB, as published. Nobody here has run it

Grafana Observability Skill

Investigate issues using Grafana's Loki (logs), Prometheus (metrics), and Tempo (traces). Works with both local and remote Grafana instances.

Configuration

The script at scripts/grafana.ts (relative to this skill) reads configuration from environment variables:

VariableDefaultDescription
GRAFANA_URLhttp://localhost:3000Grafana instance URL
GRAFANA_USER—Basic auth username (skip for unauthenticated local instances)
GRAFANA_PASSWORD—Basic auth password
GRAFANA_OP_VAULT—1Password vault name (optional, falls back to op CLI)
GRAFANA_OP_ITEM—1Password item name (optional, falls back to op CLI)

For local development with no auth, just set GRAFANA_URL and leave credentials empty.

For production/staging with 1Password:

export GRAFANA_URL="https://grafana.example.com"
export GRAFANA_OP_VAULT="platform"
export GRAFANA_OP_ITEM="Grafana Credentials"
# Fetch once, reuse for the session:
export GRAFANA_CREDS=$(op item get "$GRAFANA_OP_ITEM" --vault "$GRAFANA_OP_VAULT" --fields user,password --format json --reveal)
export GRAFANA_USER=$(echo $GRAFANA_CREDS | jq -r '.[] | select(.label=="user") | .value')
export GRAFANA_PASSWORD=$(echo $GRAFANA_CREDS | jq -r '.[] | select(.label=="password") | .value')

Running Queries

The CLI script path is relative to this skill directory:

bun run skills/grafana/scripts/grafana.ts <command> [args...]

Available Commands

CommandDescriptionExample
datasourcesList all Grafana datasourcesdatasources
alertsShow currently firing alertsalerts
loki '<logql>'Query Loki logsloki '{namespace="staging", container="api"}'
prom '<promql>'Prometheus range queryprom 'rate(container_cpu_usage_seconds_total{pod=~"api.*"}[5m])'
prom-instant '<promql>'Prometheus instant queryprom-instant 'kube_pod_container_status_restarts_total'
tempo-trace <id>Fetch a trace by IDtempo-trace abc123
tempo-search '<traceql>'Search tracestempo-search '{resource.service.name="api"}'

Time Options (apply to loki, prom, tempo-search)

  • --range <duration> — lookback from now (default: 1h). Examples: 30m, 6h, 24h, 7d
  • --start <iso> / --end <iso> — absolute time range (overrides --range)
  • --limit <n> — max results (loki default: 200, tempo default: 20)

Investigation Workflow

When investigating an alert or production issue, follow this systematic approach.

Step 1 — Parse the Alert

Extract from the alert message:

  • Namespace (e.g., production, staging)
  • Pod name and container name
  • Alert type (restart, OOM, high latency, error rate)
  • Timestamp — convert to ISO 8601 for --start/--end flags

Step 2 — Verify Namespace and Check Current State

Before deep-diving, confirm the target namespace exists. A namespace returning 0 results means it's not monitored here — flag this immediately.

# Verify the namespace exists
bun run scripts/grafana.ts prom-instant 'count(kube_pod_info{namespace="NAMESPACE"})'

# What's firing right now?
bun run scripts/grafana.ts alerts

# What datasources do we have?
bun run scripts/grafana.ts datasources

If the namespace query returns 0 results, check what namespaces ARE available:

bun run scripts/grafana.ts prom-instant 'count by (namespace) (kube_pod_info)'

Step 3 — Determine Termination Reason (for pod restarts)

bun run scripts/grafana.ts prom-instant \
  'kube_pod_container_status_last_terminated_reason{namespace="NAMESPACE", pod=~"POD_PREFIX.*"}'

bun run scripts/grafana.ts prom \
  'kube_pod_container_status_restarts_total{namespace="NAMESPACE", pod=~"POD_PREFIX.*"}' \
  --range 6h

Common termination reasons:

  • OOMKilled → container exceeded memory limit → check memory usage trend
  • Error → process crashed → check application logs for panics/exceptions
  • Completed → container exited normally → might be a misconfigured restart policy

Step 4 — Pull Logs

bun run scripts/grafana.ts loki \
  '{namespace="NAMESPACE", pod="POD_NAME", container="CONTAINER"}' \
  --range 2h --limit 500

# Filter for errors
bun run scripts/grafana.ts loki \
  '{namespace="NAMESPACE", container="CONTAINER"} |~ "(?i)(error|panic|fatal|exception|oom|killed)"' \
  --range 6h

Step 5 — Check Resource Usage

# Memory usage vs limit
bun run scripts/grafana.ts prom \
  'container_memory_working_set_bytes{namespace="NAMESPACE", pod=~"POD_PREFIX.*", container="CONTAINER"}' \
  --range 6h

# Memory limit
bun run scripts/grafana.ts prom-instant \
  'kube_pod_container_resource_limits{namespace="NAMESPACE", pod=~"POD_PREFIX.*", resource="memory"}'

# CPU usage
bun run scripts/grafana.ts prom \
  'rate(container_cpu_usage_seconds_total{namespace="NAMESPACE", pod=~"POD_PREFIX.*", container="CONTAINER"}[5m])' \
  --range 6h

Step 6 — Correlate with Traces (if available)

If logs contain trace IDs (look for traceId=, trace_id=, or hex strings):

bun run scripts/grafana.ts tempo-trace <traceId>

# Or search for error traces from a service
bun run scripts/grafana.ts tempo-search \
  '{resource.service.name="SERVICE_NAME" && status=error}' --range 2h

Step 7 — Synthesize Root Cause

After collecting data, synthesize findings:

  1. What happened: immediate symptom
  2. Why it happened: underlying cause
  3. Evidence: specific log lines, metric values, timestamps
  4. Impact: what was affected and for how long
  5. Recommendation: how to prevent recurrence

Common Kubernetes Queries

Pod Health

kube_pod_container_status_restarts_total{namespace="NS"}
kube_pod_status_phase{namespace="NS"}
kube_pod_container_status_waiting_reason{namespace="NS"}

Resource Pressure

# Memory usage / limit ratio (>0.9 = danger zone)
container_memory_working_set_bytes{namespace="NS", container!=""} /
kube_pod_container_resource_limits{namespace="NS", resource="memory", container!=""}

# CPU throttling
rate(container_cpu_cfs_throttled_seconds_total{namespace="NS"}[5m])

# Network errors
rate(container_network_receive_errors_total{namespace="NS"}[5m])

LogQL Patterns

# All errors in a namespace
{namespace="NS"} |~ "(?i)(error|fatal|panic)"

# JSON-structured logs — extract and filter fields
{namespace="NS"} | json | level="error"

# Count errors per container over time
sum by (container) (count_over_time({namespace="NS"} |~ "error" [5m]))

OpenTelemetry Note

Many modern services use OpenTelemetry instrumentation, not standard Prometheus metric names. If standard http_requests_total / http_request_duration_seconds_bucket metrics return 0 series, pivot to Tempo traces for latency analysis — they provide per-request timing with middleware breakdown.

bun run scripts/grafana.ts tempo-search \
  '{resource.service.name="SERVICE" && duration>1s}' --range 1h

Keep looking

Skills are one crate of 628,971. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.