Skip to main content
skill CX Codex

prometheus-grafana — Claude Code skill: metrics and dashboards

This skill gives your agent templates for Prometheus scraping, PromQL queries and Grafana panels. Handy when a project needs monitoring added.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add BagelHole/DevOps-Security-Agent-Skills --skill prometheus-grafana -a claude-code
Open on GitHub

What prometheus-grafana does

The skill hands the agent ready-made pieces for a Prometheus and Grafana stack. Inside are a docker-compose.yml with both services, a prometheus.yml with scrape jobs, alert rules in rules/alerts.yml, and PromQL examples such as rate(http_requests_total[5m]), histogram_quantile(0.95, ...) and predict_linear(node_filesystem_avail_bytes[1h], 4 * 3600).

There is a Kubernetes path too: installing kube-prometheus-stack with Helm and a ServiceMonitor manifest. A separate section covers Alertmanager routing to Slack and PagerDuty. For Grafana you get dashboard JSON structure and file-based provisioning of data sources.

You need Docker or Kubernetes to deploy, plus network access to the targets you want to scrape. Without those, the templates stay text. Some grasp of metrics helps as well — counters versus histograms — otherwise the queries are guesswork. The Grafana admin password in the example is admin; swap it before anything real runs.

What it helps with

  • stand up Prometheus and Grafana with docker-compose
  • define scrape jobs for node-exporter and app targets
  • write PromQL for error ratio and latency percentiles
  • add alert rules for service down and low disk space
  • deploy kube-prometheus-stack to a cluster via Helm

Example prompts for the agent

  • Set up metrics collection for my app with Prometheus, Grafana and Slack alerts
  • Write PromQL for the 95th percentile latency per endpoint
  • Build a Grafana dashboard with a request rate graph and a latency P95 gauge

How to install prometheus-grafana

1Skills CLI (Vercel)

npx skills add BagelHole/DevOps-Security-Agent-Skills --skill prometheus-grafana -a claude-code

2Manually: put the files in place

~/.claude/skills/prometheus-grafana/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/prometheus-grafana/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about prometheus-grafana

How do I install prometheus-grafana in Claude?

Run npx skills add BagelHole/DevOps-Security-Agent-Skills --skill prometheus-grafana -a claude-code. The skill lands at ~/.claude/skills/prometheus-grafana/SKILL.md.

What does the prometheus-grafana skill do?

It helps the agent set up metrics collection and visualization: Prometheus configs, PromQL queries, alert rules, Grafana dashboards and data source provisioning.

What do I need before using it?

Docker or Kubernetes for deployment and network access to the services you monitor. A basic feel for metrics also helps, or PromQL gets confusing fast.

Source text

SKILL.md · MIT
---
name: prometheus-grafana
description: Set up metrics collection and visualization with Prometheus and Grafana. Configure scrape targets, create PromQL queries, build dashboards, and implement alerting. Use when implementing monitoring, metrics collection, or visualization for applications and infrastructure.
license: MIT
metadata:
  author: devops-skills
  version: "1.0"
---

# Prometheus & Grafana

Collect metrics and visualize system performance with the Prometheus-Grafana stack.

## When to Use This Skill

Use this skill when:
- Setting up metrics collection infrastructure
- Creating monitoring dashboards
- Writing PromQL queries for analysis
- Configuring alerting rules
- Monitoring Kubernetes clusters

## Prerequisites

- Docker or Kubernetes for deployment
- Network access to monitored targets
- Basic understanding of metrics concepts

## Prometheus Setup

### Docker Deployment

```yaml
# docker-compose.yml
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:v2.48.0
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - ./rules:/etc/prometheus/rules
      - prometheus-data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=15d'

  grafana:
    image: grafana/grafana:10.2.0
    ports:
      - "3000:3000"
    volumes:
      - grafana-data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin

volumes:
  prometheus-data:
  grafana-data:
```

### Configuration

```yaml
# prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

alerting:
  alertmanagers:
    - static_configs:
        - targets:
            - alertmanager:9093

rule_files:
  - /etc/prometheus/rules/*.yml

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node'
    static_configs:
      - targets:
          - 'node-exporter:9100'

  - job_name: 'applications'
    static_configs:
      - targets:
          - 'app1:8080'
          - 'app2:8080'
    metrics_path: /metrics
```

## Kubernetes Deployment

### Using Helm

```bash
# Add Prometheus community Helm repo
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts

# Install kube-prometheus-stack
helm install prometheus prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --create-namespace \
  --set grafana.adminPassword=admin
```

### ServiceMonitor

```yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: myapp
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: myapp
  endpoints:
    - port: metrics
      interval: 30s
      path: /metrics
  namespaceSelector:
    matchNames:
      - default
```

## PromQL Queries

### Basic Queries

```promql
# Current CPU usage
node_cpu_seconds_total{mode="idle"}

# Rate of HTTP requests per second
rate(http_requests_total[5m])

# Average response time
avg(http_request_duration_seconds_sum / http_request_duration_seconds_count)

# Memory usage percentage
(1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100
```

### Aggregations

```promql
# Sum requests by status code
sum by (status_code) (rate(http_requests_total[5m]))

# Average CPU by instance
avg by (instance) (rate(node_cpu_seconds_total{mode!="idle"}[5m]))

# Top 5 endpoints by request count
topk(5, sum by (endpoint) (rate(http_requests_total[5m])))

# 95th percentile latency
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))
```

### Time-Based Queries

```promql
# Compare to 1 hour ago
http_requests_total - http_requests_total offset 1h

# Predict disk space in 4 hours
predict_linear(node_filesystem_avail_bytes[1h], 4 * 3600)

# Changes in last 5 minutes
changes(up[5m])

# Average over 24 hours
avg_over_time(http_requests_total[24h])
```

## Alerting Rules

```yaml
# rules/alerts.yml
groups:
  - name: application
    rules:
      - alert: HighErrorRate
        expr: |
          sum(rate(http_requests_total{status=~"5.."}[5m]))
          / sum(rate(http_requests_total[5m])) > 0.05
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "High error rate detected"
          description: "Error rate is {{ $value | humanizePercentage }}"

      - alert: ServiceDown
        expr: up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Service {{ $labels.instance }} is down"

      - alert: HighMemoryUsage
        expr: |
          (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) > 0.9
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "High memory usage on {{ $labels.instance }}"
          description: "Memory usage is {{ $value | humanizePercentage }}"

      - alert: DiskSpaceLow
        expr: |
          (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) < 0.1
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "Disk space low on {{ $labels.instance }}"
```

## Alertmanager

```yaml
# alertmanager.yml
global:
  resolve_timeout: 5m
  slack_api_url: 'https://hooks.slack.com/services/xxx'

route:
  receiver: 'slack-notifications'
  group_by: ['alertname', 'severity']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  routes:
    - match:
        severity: critical
      receiver: 'pagerduty'

receivers:
  - name: 'slack-notifications'
    slack_configs:
      - channel: '#alerts'
        send_resolved: true
        title: '{{ .Status | toUpper }}: {{ .CommonAnnotations.summary }}'
        text: '{{ .CommonAnnotations.description }}'

  - name: 'pagerduty'
    pagerduty_configs:
      - service_key: 'xxx'
        severity: critical
```

## Grafana Dashboards

### Dashboard JSON Structure

```json
{
  "dashboard": {
    "title": "Application Metrics",
    "panels": [
      {
        "title": "Request Rate",
        "type": "graph",
        "targets": [
          {
            "expr": "sum(rate(http_requests_total[5m])) by (status_code)",
            "legendFormat": "{{ status_code }}"
          }
        ],
        "gridPos": {"x": 0, "y": 0, "w": 12, "h": 8}
      },
      {
        "title": "Latency P95",
        "type": "gauge",
        "targets": [
          {
            "expr": "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))"
          }
        ],
        "gridPos": {"x": 12, "y": 0, "w": 6, "h": 8}
      }
    ]
  }
}
```

### Provisioning Dashboards

```yaml
# grafana/provisioning/dashboards/dashboards.yml
apiVersion: 1

providers:
  - name: 'default'
    orgId: 1
    folder: ''
    type: file
    disableDeletion: false
    updateIntervalSeconds: 30
    options:
      path: /var/lib/grafana/dashboards
```

### Data Source Provisioning

```yaml
# grafana/provisioning/datasources/prometheus.yml
apiVersion: 1

datasources:
  - name: Prometheus
    type: prometheus
    access: proxy
    url: http://prometheus:9090
    isDefault: true
    editable: false
```

## Recording Rules

```yaml
# rules/recording.yml
groups:
  - name: aggregations
    interval: 30s
    rules:
      - record: job:http_requests:rate5m
        expr: sum by (job) (rate(http_requests_total[5m]))

      - record: instance:node_cpu:avg_rate5m
        expr: |
          avg by (instance) (
            rate(node_cpu_seconds_total{mode!="idle"}[5m])
          )

      - record: job:http_latency:p95
        expr: |
          histogram_quantile(0.95,
            sum by (job, le) (rate(http_request_duration_seconds_bucket[5m]))
          )
```

## Application Instrumentation

### Go Application

```go
import (
    "github.com/prometheus/client_golang/prometheus"
    "github.com/prometheus/client_golang/prometheus/promhttp"
)

var httpRequests = prometheus.NewCounterVec(
    prometheus.CounterOpts{
        Name: "http_requests_total",
        Help: "Total HTTP requests",
    },
    []string{"method", "endpoint", "status"},
)

func init() {
    prometheus.MustRegister(httpRequests)
}

// Expose metrics endpoint
http.Handle("/metrics", promhttp.Handler())
```

### Node.js Application

```javascript
const client = require('prom-client');

const httpRequests = new client.Counter({
  name: 'http_requests_total',
  help: 'Total HTTP requests',
  labelNames: ['method', 'endpoint', 'status']
});

// Middleware
app.use((req, res, next) => {
  res.on('finish', () => {
    httpRequests.inc({
      method: req.method,
      endpoint: req.path,
      status: res.statusCode
    });
  });
  next();
});

// Expose metrics
app.get('/metrics', async (req, res) => {
  res.set('Content-Type', client.register.contentType);
  res.end(await client.register.metrics());
});
```

## Common Issues

### Issue: Targets Not Discovered
**Problem**: Prometheus not scraping targets
**Solution**: Check network connectivity, verify target labels

### Issue: High Memory Usage
**Problem**: Prometheus using excessive memory
**Solution**: Reduce retention, use recording rules, limit cardinality

### Issue: Slow Queries
**Problem**: PromQL queries timing out
**Solution**: Use recording rules, limit time ranges, optimize queries

### Issue: Missing Data Points
**Problem**: Gaps in metrics data
**Solution**: Check scrape interval, verify target availability

## Best Practices

- Use recording rules for frequently-used queries
- Limit label cardinality to prevent memory issues
- Set appropriate retention based on storage capacity
- Use histogram metrics for latency measurement
- Implement proper alerting thresholds
- Version control dashboards as code
- Use federation for large-scale deployments
- Regularly review and prune unused metrics

## Related Skills

- [alerting-oncall](../alerting-oncall/) - Alert management
- [loki-logging](../loki-logging/) - Log aggregation
- [kubernetes-ops](../../orchestration/kubernetes-ops/) - K8s monitoring

© devops-skills · MIT · BagelHole/DevOps-Security-Agent-Skills

Similar skills

Everything for DevOps and infrastructure →

From the same set127

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor