一键导入
monitoring-grafana
Grafana monitoring, visualization, and alerting. Use when working with Grafana datasources, Prometheus metrics, Loki logs, dashboards, or alerts.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Grafana monitoring, visualization, and alerting. Use when working with Grafana datasources, Prometheus metrics, Loki logs, dashboards, or alerts.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Cloudflare GraphQL Analytics for zone traffic, firewall events, Workers metrics, and schema exploration. Use when querying Cloudflare analytics data or exploring the GraphQL API.
PostgreSQL database analysis, performance tuning, and health monitoring. You MUST read this entire skill document before executing any PostgreSQL operations — it contains mandatory workflows, safety constraints, and two-phase execution rules that prevent common errors like hallucinated column names and unsafe queries.
SonarQube code quality and security analysis. Use when working with code quality metrics, security hotspots, quality gates, or issue tracking in SonarQube Cloud or Server.
Use when working with Aws Billing — analyze, break down, and report AWS costs and bills. Covers cost breakdown by service, account, or usage type; monthly/daily billing trends; cost anomaly detection; RI/SP utilization; cost forecasting; credit/discount analysis; and multi-account cost comparison. Uses anti-hallucination rules, mandatory currency/credit detection workflow, and reusable Cost Explorer functions.
Use when working with Aws Idle Resources — detect unused and idle AWS resources that incur cost without providing value. Covers detached EBS volumes, idle load balancers, unused Elastic IPs, stopped EC2 instances, idle NAT Gateways, old snapshots, and unused ENIs. Includes estimated monthly waste per resource and anti-hallucination rules for safe detection.
Use when working with Aws Pricing — aWS pricing helper for cost queries. ALWAYS use get_aws_cost script for pricing questions. Use when: - User asks about AWS resource costs or pricing - User wants to compare pricing across regions - User needs spot, on-demand, or reserved pricing info Triggers: aws pricing, aws cost, how much does, ec2 price, rds cost, s3 pricing.
| name | monitoring-grafana |
| description | Grafana monitoring, visualization, and alerting. Use when working with Grafana datasources, Prometheus metrics, Loki logs, dashboards, or alerts. |
| connection_type | grafana |
| preload | false |
What discovery provides:
datasources: All datasources with uid, name, type, isDefault (grouped by type)dashboards: Available dashboards with uid, title, folderTitle, tagsfolders: Dashboard folders with uid, titlealerts: Alert rules with total count, state breakdown, and firing alerts listincidents: Active incidents with id, title, statusprometheus: Per-datasource label discovery (labelNames, keyLabels for job/namespace/instance)loki: Per-datasource label discovery (labelNames, keyLabels for app/namespace/pod)capabilities: siftAvailable - whether Sift plugin is installed (for find_error_pattern_logs)hints.loki: Query limits, forbidden regex patterns, and safe alternativesWhy run discovery:
datasourceUid required for all Prometheus/Loki queriesfind_error_pattern_logs will work)// ✅ CORRECT - always specify at least one label await query_loki_logs({ datasourceUid, logql: '{app="backend"}', limit: 50 }); await query_loki_stats({ datasourceUid, logql: '{namespace="prod"}' });
Use discovery (`list_loki_label_values`) to find valid label values if you don't know them.
</critical>
| Bad ❌ | Good ✅ | Why |
|--------|---------|-----|
| `expr: 'node_cpu_total'` | `expr: 'avg(rate(node_cpu_total[5m]))'` | Aggregation reduces 100+ series to 1 |
| `queryType: "range"` for current value | `queryType: "instant"` | Single point vs 60+ points |
| `limit: 1000` | `limit: 20-50` first | Sample before fetching all |
| `startTime: "now-24h"` | `startTime: "now-15m"` | Recent data sufficient for troubleshooting |
| `query_loki_logs()` first | `find_error_pattern_logs()` first | Patterns before raw logs |
**Query progression**: Aggregated summary → Filter to problem area → Small sample → (rarely) Full data
## Tools
**Datasources:** `list_datasources(type?)`, `get_datasource(uid?, name?)`
**Dashboards:** `search_dashboards(query?)`, `get_dashboard_by_uid(uid)`, `get_dashboard_summary(uid)`, `get_dashboard_panel_queries(uid, panelId)`, `get_dashboard_property(uid, jsonPath)`, `update_dashboard(dashboard?, uid?, operations?, folderUid?, message?, overwrite?)`, `run_panel_query(dashboardUid, panelIds, queryIndex?, start?, end?, variables?)`, `search_folders(query?)`, `create_folder(title, uid?, parentUid?)`
**Prometheus:** `query_prometheus(datasourceUid, expr, startTime, queryType?, endTime?, stepSeconds?)`, `query_prometheus_histogram(datasourceUid, metric, percentile, labels?, rateInterval?, startTime?, endTime?, stepSeconds?)`, `list_prometheus_metric_names(datasourceUid)`, `list_prometheus_label_names(datasourceUid, match?)`, `list_prometheus_label_values(datasourceUid, labelName, match?)`, `list_prometheus_metric_metadata(datasourceUid)`
**Loki:** `query_loki_logs(datasourceUid, logql, startRfc3339?, endRfc3339?, limit?, direction?)`, `query_loki_stats(datasourceUid, logql, startRfc3339?, endRfc3339?)`, `list_loki_label_names(datasourceUid, startRfc3339?, endRfc3339?)`, `list_loki_label_values(datasourceUid, labelName, startRfc3339?, endRfc3339?)`, `find_error_pattern_logs(name, labels, start?, end?)`, `find_slow_requests(name, labels, start?, end?)`, `query_loki_patterns(datasourceUid, logql, startRfc3339?, endRfc3339?, step?)`
**Alerting:** `alerting_manage_rules(operation: "list"|"get"|"create"|"update"|"delete", rule_uid?, ...)`, `list_alert_groups(...)`, `alerting_manage_routing(operation: "get_notification_policies"|"get_contact_points"|..., ...)`
**Annotations:** `get_annotations(...)`, `create_annotation(...)`, `update_annotation(...)`, `get_annotation_tags(...)`
**Incidents:** `list_incidents(...)`, `get_incident(incidentId)`, `create_incident(...)`, `add_activity_to_incident(incidentId, body, eventTime?)`, `list_oncall_schedules(...)`, `get_current_oncall_users(scheduleId)`
**Search:** `search_logs(datasourceUid, pattern, table?, start?, end?, limit?)`
**Elasticsearch:** `query_elasticsearch(datasourceUid, query, start?, end?, limit?)`
**CloudWatch:** `query_cloudwatch(datasourceUid, namespace, metricName, dimensions?, statistic?, period?, start?, end?, region, accountId?)`
**ClickHouse:** `query_clickhouse(datasourceUid, query, start?, end?, variables?, limit?)`, `list_clickhouse_tables(datasourceUid)`
**Pyroscope:** `list_pyroscope_label_names(data_source_uid, ...)`, `list_pyroscope_label_values(...)`, `list_pyroscope_profile_types(data_source_uid)`, `fetch_pyroscope_profile(...)`
**Rendering:** `get_panel_image(dashboardUid, panelId?, width?, height?, timeRange?, variables?, theme?, scale?)`
**Navigation:** `generate_deeplink(resourceType, dashboardUid?, datasourceUid?, panelId?, queryParams?, timeRange?)`
**Admin:** `list_teams(query?)`, `list_users_by_org()`, `list_all_roles(delegatableOnly?)`, `get_role_details(roleUID)`
**Examples:** `get_query_examples(datasourceType)`
**Sift:** `start_sift_investigation(...)`, `get_sift_investigation_status(...)`, `list_sift_investigations(...)`
**Asserts:** `get_assertions(startTime, endTime, entityType, entityName, ...)`
## Quick Patterns
**Discover:**
```typescript
const datasources = await list_datasources({ type: "prometheus" });
const labels = await list_prometheus_label_names({ datasourceUid: "ds-uid" });
const apps = await list_loki_label_values({ datasourceUid: "ds-uid", labelName: "app" });
LogQL: {label="value"} |= "filter" - Examples: {app="backend"}, {app="backend"} |= "error", {app="backend"} | json | status >= 500
import type { QueryLokiLogsResult, QueryLokiStatsResult } from "./_skills/connections/grafana/monitoring-grafana/schemas";
// Stats query (label matchers only, no line filters)
const stats = await query_loki_stats({
datasourceUid, logql: '{app="backend", namespace="prod"}'
}) as QueryLokiStatsResult;
// Log query with line filter
const response = await query_loki_logs({
datasourceUid, logql: '{app="backend"} |= "error"', limit: 100, direction: "backward"
}) as QueryLokiLogsResult;
const logs = response.data;
// Strip JSON quotes bug: timestamp.replace(/^"|"$/g, '') then new Date(Number(ts) / 1e6)
**REGEX LIMITS:** Loki rejects `\w`, `\d`, `\s`, `\b`, `(?i)` - use `[A-Za-z0-9_]`, `[0-9]`, `[ \t]`, alternation `[Ee]rror|[Ww]arn`
**LOGQL OR SYNTAX:** Cannot chain `|=` with `or`. Use regex alternation instead.
```typescript
// ❌ WRONG - "or" cannot chain line filters
'{namespace="prod"} |= "error" or |= "ERROR" or |= "Exception"'
// ✅ CORRECT - regex alternation '{namespace="prod"} |~ "error|ERROR|Exception|FATAL"'
// ✅ BEST - broad query + TypeScript filtering const response = await query_loki_logs({...logql: '{namespace="prod"}', limit: 100}) as QueryLokiLogsResult; const errors = response.data.filter(l => /error|exception|fatal/i.test(l.line));
</critical>
<critical>
**RATE LIMITS:** Max 2-3 concurrent queries (429 error otherwise). **Prefer single broad query + TypeScript filtering** over parallel queries.
```typescript
const response = await query_loki_logs({datasourceUid, logql: '{namespace="prod"}', limit: 100}) as QueryLokiLogsResult;
const errors = response.data.filter(l => /error/i.test(l.line)); // Filter in code
**`query_loki_stats` ONLY SUPPORTS LABEL MATCHERS** - No line filters (`|=`, `|~`), no parser (`| json`), no label filters.
```typescript
// ❌ WRONG - will fail with "only label matchers is supported"
await query_loki_stats({datasourceUid, logql: '{app="backend"} |= "error"', ...});
// ✅ CORRECT - label matchers only await query_loki_stats({datasourceUid, logql: '{app="backend", namespace="prod"}', ...});
// Then filter with query_loki_logs if needed const logs = await query_loki_logs({datasourceUid, logql: '{app="backend"} |= "error"', limit: 100});
</critical>
<critical>
**SIFT PLUGIN:** `find_error_pattern_logs()` / `find_slow_requests()` may return 404. Always use try-catch with manual fallback:
```typescript
try {
patterns = await find_error_pattern_logs({name: "error-analysis", labels: {namespace: "prod"}});
} catch (e: any) {
if (e.message?.includes('404')) {
const patternMap = new Map<string, number>();
logs.forEach(log => {
const p = log.line.substring(0, 100).trim();
patternMap.set(p, (patternMap.get(p) || 0) + 1);
});
patterns = Array.from(patternMap.entries()).sort((a, b) => b[1] - a[1]).slice(0, 10);
} else throw e;
}
Best Workflow: Single broad query → TypeScript categorization → pattern detection
const response = await query_loki_logs({datasourceUid, logql: '{namespace="prod"}', limit: 100, direction: 'backward'}) as QueryLokiLogsResult;
const logs = response.data;
const errors = logs.filter(l => /error/i.test(l.line));
const patternMap = new Map<string, number>();
errors.forEach(log => {
const p = log.line.substring(0, 100).trim();
patternMap.set(p, (patternMap.get(p) || 0) + 1);
});
const top5 = Array.from(patternMap.entries()).sort((a, b) => b[1] - a[1]).slice(0, 5);
PromQL: avg(rate(...[5m])) by (label), topk(5, ...), histogram_quantile(0.95, ...)
// Current state (instant query)
const p95 = await query_prometheus({datasourceUid, expr: 'histogram_quantile(0.95, rate(http_duration_bucket[5m]))', startTime: "now", queryType: "instant"});
// Trend (short range)
const trend = await query_prometheus({datasourceUid, expr: 'avg(rate(http_requests[5m])) by (status)', startTime: "now-15m", queryType: "range", stepSeconds: 60});
Dashboards: search_dashboards({query}), get_dashboard_summary({uid}), get_dashboard_panel_queries({uid, panelId})
Alerts: alerting_manage_rules({operation: "list"}), alerting_manage_rules({operation: "get", rule_uid: uid})
Errors: find_error_pattern_logs({name: "...", labels: {...}}) → query_loki_logs(limit:20) for top pattern
Performance: query_prometheus(instant) P95 → if high, query_prometheus(range, now-15m) trend
Alerts: alerting_manage_rules({operation: "list"}) filter state:"firing" → query_prometheus(now-15m) for alert metric
Time: Prometheus: now-1h, Loki: RFC3339 2024-01-07T00:00:00Z
Common Errors:
{} → Loki rejects logql: '{}' with parse error: unexpected }, expecting IDENTIFIER. Always include at least one label matcher (e.g., {app="backend"}, {namespace="prod"}). Use list_loki_label_values() to discover available labels.ts.replace(/^"|"$/g, '') then new Date(Number(ts)/1e6)\w → Use [A-Za-z0-9_]query_loki_stats with filters → Stats only supports label matchers, no line filters (|=, |~, | json)Raw metrics first: Use aggregation (sum, avg, rate, topk) before fetching series
Range for current state: Use queryType: "instant" not "range"
Long time windows: Start now-15m not now-1h or now-24h
High log limits: Use limit: 20-50 not 500+ for exploration
Logs before patterns: Use find_error_pattern_logs() or query_loki_stats() first
Complex regex: Use [A-Za-z0-9_] not \w, or filter in TypeScript
3+ parallel queries: Rate limit 2-3 max, prefer single query + code filter
Assuming Sift: Always try-catch with manual fallback (404 error)
Present results as a structured report:
Monitoring Grafana Report
═════════════════════════
Resources discovered: [count]
Resource Status Key Metric Issues
──────────────────────────────────────────────
[name] [ok/warn] [value] [findings]
Summary: [total] resources | [ok] healthy | [warn] warnings | [crit] critical
Action Items: [list of prioritized findings]
Target ≤50 lines of output. Use tables for multi-resource comparisons.
--help output.| Shortcut | Counter | Why |
|---|---|---|
| "I'll skip discovery and check known resources" | Always run Phase 1 discovery first | Resource names change, new resources appear — assumed names cause errors |
| "The user only asked for a quick check" | Follow the full discovery → analysis flow | Quick checks miss critical issues; structured analysis catches silent failures |
| "Default configuration is probably fine" | Audit configuration explicitly | Defaults often leave logging, security, and optimization features disabled |
| "Metrics aren't needed for this" | Always check relevant metrics when available | API/CLI responses show current state; metrics reveal trends and intermittent issues |
| "I don't have access to that" | Try the command and report the actual error | Assumed permission failures prevent useful investigation; actual errors are informative |