<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: building-soc-metrics-dashboard
description: >-
  Design and implement SOC operational metrics dashboards tracking MTTD, MTTR,
  false positive rate, alert volume, analyst throughput, detection coverage, and
  SOC maturity indicators using Splunk dashboards, Elastic Kibana, and Grafana.
domain: cybersecurity
subdomain: soc-operations
tags:
  - soc-metrics
  - dashboard
  - mttd
  - mttr
  - splunk
  - kibana
  - grafana
  - soc-maturity
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: []
---

# Building SOC Metrics Dashboard

## Overview

SOC metrics dashboards provide visibility into operational performance,
detection effectiveness, and analyst workload. Effective dashboards drive
data-informed decisions about staffing, detection tuning, and automation
investment. This skill covers metric definitions, SIEM queries, and
dashboard construction.

## Prerequisites

| Requirement | Purpose |
|---|---|
| SIEM with notable/alert data | Metric source data |
| Dashboard platform (Splunk/Kibana/Grafana) | Visualization |
| Alert disposition workflow | FP/TP classification data |
| Shift schedule data | Analyst workload analysis |

## Key Concepts

### Core SOC Metrics

```
OPERATIONAL METRICS:
├── MTTD (Mean Time to Detect)
│   Formula: avg(alert_time - event_time)
│   Target: < 24 hours for most threats
│   
├── MTTR (Mean Time to Respond)
│   Formula: avg(response_time - alert_time)
│   Target: < 4 hours (< 1 hour for critical)
│   
├── MTTC (Mean Time to Contain)
│   Formula: avg(containment_time - detection_time)
│   Target: < 1 hour for critical incidents
│   
├── False Positive Rate (FPR)
│   Formula: false_positives / total_alerts * 100
│   Target: < 30% per detection rule
│   
├── Alert Volume
│   Track: daily/weekly trend, by severity, by source
│   Alert: investigate sudden spikes
│   
├── Escalation Rate
│   Formula: escalated_alerts / total_alerts
│   Target: T1→T2 = 10-20%
│   
└── Detection Coverage
    Formula: techniques_with_rules / total_techniques
    Target: > 50% of relevant ATT&CK techniques
```

### Splunk Dashboard Queries

```spl
-- MTTR by severity (last 30 days)
index=notable status_label="Closed" OR status_label="Resolved"
| where _time > relative_time(now(), "-30d")
| eval detect_to_close_hours = (status_end - _time) / 3600
| stats avg(detect_to_close_hours) as avg_mttr,
    median(detect_to_close_hours) as median_mttr,
    perc95(detect_to_close_hours) as p95_mttr
    by urgency
| eval avg_mttr=round(avg_mttr, 2)
| sort urgency

-- Alert volume trend (daily, 30 days)
index=notable
| where _time > relative_time(now(), "-30d")
| timechart span=1d count by urgency

-- FP rate by rule (top offenders)
index=notable
| where _time > relative_time(now(), "-30d")
| stats count as total,
    sum(eval(if(status_label="False Positive", 1, 0))) as fp
    by search_name
| eval fp_rate=round(fp/total*100, 1)
| where total > 10
| sort -fp_rate
| head 20

-- Analyst throughput per shift
index=notable status_label!="new"
| eval shift=case(
    date_hour>=0 AND date_hour<8, "Night",
    date_hour>=8 AND date_hour<16, "Day",
    1==1, "Swing")
| stats dc(event_id) as alerts_handled by owner, shift
| sort shift, -alerts_handled

-- Detection coverage heatmap data
| inputlookup mitre_attack_lookup
| join type=left technique_id
    [search index=notable | stats dc(search_name) as rules by technique_id]
| fillnull rules value=0
| table technique_id, technique_name, tactic, rules
```

### Kibana Dashboard Queries

```
// Alert volume by severity (Elastic)
kibana.alert.severity:* AND kibana.alert.status:*
| date_histogram(field: "@timestamp", interval: "1d")
  aggs: terms(field: "kibana.alert.severity")

// MTTR calculation (Elastic)
kibana.alert.workflow_status:"closed"
| avg(kibana.alert.duration)
  by: kibana.alert.severity
```

### Grafana + Prometheus Metrics

```yaml
# SOC metrics exporter config
metrics:
  - name: soc_alert_total
    type: counter
    labels: [severity, source, disposition]
    help: "Total alerts by severity and disposition"

  - name: soc_mttr_seconds
    type: histogram
    labels: [severity]
    buckets: [900, 1800, 3600, 7200, 14400, 28800, 86400]
    help: "Mean time to respond in seconds"

  - name: soc_detection_coverage_ratio
    type: gauge
    help: "Ratio of ATT&CK techniques with active detections"
```

## Workflow

1. **Define** — Select metrics aligned with SOC maturity goals
2. **Source** — Identify SIEM data for each metric calculation
3. **Query** — Build and validate metric queries
4. **Visualize** — Create dashboard panels with appropriate chart types
5. **Threshold** — Set targets and color-code against baselines
6. **Automate** — Schedule dashboard refresh and alert on deviations
7. **Review** — Present metrics in weekly SOC leadership briefing
8. **Iterate** — Refine metrics based on operational feedback

## Verification

| Check | Method |
|---|---|
| Metrics calculated correctly | Manual spot-check vs. raw data |
| Dashboard loads within 30s | Performance test |
| Data refreshes on schedule | Verify last update timestamp |
| Thresholds trigger alerts | Test with known values |
| All panels populated | Visual review across time ranges |
