Prometheus and Grafana
Medusa can expose internal metrics (battery states, track counts, engagement rates, Pk values, timing data) in Prometheus format. When enabled, it writes a metrics file to your DCS Saved Games directory. A Docker stack reads that file into Prometheus, which feeds Grafana dashboards and the tactical display.
Prerequisites
Section titled “Prerequisites”- Docker Desktop (or Docker Engine + Docker Compose)
- DCS World desanitization. Medusa needs
ioandlfsto write the metrics file. In your DCS installation directory, editScripts/MissionScripting.luaand uncomment or add theioandlfslines so they are not set to nil.
Enabling metrics in your mission
Section titled “Enabling metrics in your mission”Add PrometheusEnabled = true to your config before loading Medusa:
MEDUSA_CONFIG = { PrometheusEnabled = true, Networks = { { name = "RED", coalition = "red", prefix = "iads" }, },}Medusa writes Logs/medusa_metrics.prom in your DCS Saved Games directory every 10 seconds. This file contains all metrics in Prometheus text format.
For per-battery and per-track detail (positions, ammo, Pk values, engagement ranges), enable extended metrics:
MEDUSA_CONFIG = { PrometheusEnabled = true, PrometheusExtendEnabled = true, -- writes every 2 seconds instead of 10}Extended metrics add more DCS API calls per write cycle. On large missions with many batteries, this can add a few milliseconds of overhead per write.
Starting the Docker stack
Section titled “Starting the Docker stack”If you have Task installed (recommended):
task prometheusOr with Docker Compose directly:
cd tools/prometheusdocker compose up -dOther Task commands: task prometheus:stop to shut down, task prometheus:restart to restart, task prometheus:reset to wipe all stored data.
This starts four containers:
| Container | Port | What it does |
|---|---|---|
medusa-node-exporter | 9100 | Reads the .prom file from your DCS Logs directory and serves it to Prometheus |
medusa-prometheus | 9090 | Scrapes the node exporter every 3 seconds and stores 30 days of data |
medusa-grafana | 3000 | Dashboards. Login: admin / medusa. Anonymous viewing enabled. |
medusa-tactical | 8080 | Tactical display web app. Requires PrometheusExtendEnabled = true. See Tactical Display |
Pointing to your DCS Logs directory
Section titled “Pointing to your DCS Logs directory”The stack reads the DCS Logs path from tools/prometheus/.env. Edit this file to match your setup:
DCS_LOGS_PATH=C:\Users\YourName\Saved Games\DCS.openbeta\LogsGrafana dashboards
Section titled “Grafana dashboards”Four dashboards are pre-configured:
Medusa Overview. Network-wide status: battery states, track counts by identification, engagement rates, shots/kills, Rolling Pk, HARM response activity, ammo remaining.
Medusa Performance. Per-phase timing: tick duration, sensor polling, track classification, HARM evaluation, target assignment, handoff, EMCON. Shows p50, p90, p99 for each.
Medusa Battery Details. Per-battery drill-down: ammo, engagement range, weapon range, HARM defense status, last-chance salvo status.
Medusa Track Details. Per-track analysis: track age at expiry, update count distribution, best/second Pk values.
All dashboards filter by network using a $network dropdown at the top. When the mission is not running, panels go blank (they gate on the medusa:live recording rule which checks if the heartbeat is fresh).
Liveness detection
Section titled “Liveness detection”Medusa writes a medusa_heartbeat_epoch gauge on every metrics export. A Prometheus recording rule called medusa:live checks if the heartbeat is less than 30 seconds old. All dashboard panels and the tactical display use this to hide stale data when the mission stops.
Metric reference
Section titled “Metric reference”Metrics are prefixed with medusa_. Counters end in _total. Summaries include _count and _sum suffixes plus quantile labels.
Standard metrics
Section titled “Standard metrics”These are always available when PrometheusEnabled = true.
| Metric | Type | Description |
|---|---|---|
medusa_mission_time_seconds | gauge | Seconds since mission start |
medusa_mission_info | info | Current mission name |
medusa_batteries_total | gauge | Total batteries in network |
medusa_sensors_total | gauge | Total sensors in network |
medusa_tracks_active | gauge | Active tracks |
medusa_batteries_hot | gauge | Batteries in HOT state |
medusa_batteries_warm | gauge | Batteries in WARM state |
medusa_batteries_cold | gauge | Batteries in COLD state |
medusa_engagements_active | gauge | Batteries currently engaging |
medusa_tracks_hostile | gauge | HOSTILE tracks |
medusa_tracks_harm | gauge | Tracks assessed as HARM |
medusa_tracks_bandit | gauge | BANDIT tracks |
medusa_tracks_bogey | gauge | BOGEY tracks |
medusa_tracks_unknown | gauge | UNKNOWN tracks |
medusa_tracks_sprt_evaluating | gauge | Tracks under HARM evaluation |
medusa_ammo_remaining | gauge | Total missiles remaining |
medusa_batteries_rearming | gauge | Batteries out of ammo |
medusa_batteries_damaged | gauge | Batteries with degraded status |
medusa_batteries_shutdown | gauge | Batteries in HARM shutdown |
medusa_batteries_suppressed | gauge | Batteries suppressed by HARMs |
medusa_batteries_self_defending | gauge | Batteries self-defending against HARMs |
medusa_batteries_pd_protected | gauge | Batteries protected by point defense |
medusa_rolling_pk | gauge | Network rolling kill rate |
medusa_effective_pk_floor | gauge | Effective PkFloor after rolling adjustment |
medusa_ticks_total | counter | Total ticks processed |
medusa_battery_go_hot_total | counter | HOT transitions |
medusa_battery_go_warm_total | counter | WARM transitions |
medusa_battery_go_cold_total | counter | COLD transitions |
medusa_battery_destroyed_total | counter | Batteries destroyed |
medusa_shots_fired_total | counter | Shots fired |
medusa_kills_total | counter | Kills scored |
medusa_tracks_created_total | counter | Tracks created |
medusa_tracks_expired_total | counter | Tracks expired |
medusa_engagements_assigned_total | counter | Engagements assigned |
medusa_harm_confirmed_total | counter | Tracks confirmed as HARM |
medusa_harm_shutdowns_total | counter | HARM shutdowns |
medusa_last_chance_activated_total | counter | Last-chance salvo windows opened |
medusa_last_chance_fired_total | counter | Shots during last-chance |
medusa_roe_changes_total | counter | Runtime ROE changes via API |
medusa_track_promotions_total | counter | Track identification promotions |
medusa_assignment_pairs_evaluated | counter | Battery-track pairs evaluated |
medusa_detections_total | counter | Sensor detections |
medusa_goHot_blocked_total | counter | goHot calls blocked |
medusa_sensor_empty_polls_total | counter | Empty sensor polls |
medusa_tick_duration_seconds | summary | Tick processing time (p50/p90/p99) |
medusa_poll_sensors_duration_seconds | summary | Sensor polling time |
medusa_prune_stale_duration_seconds | summary | Track pruning time |
medusa_classification_duration_seconds | summary | Track classification time |
medusa_harm_eval_duration_seconds | summary | HARM detection + response time |
medusa_assignment_duration_seconds | summary | Target assignment time |
medusa_handoff_duration_seconds | summary | Handoff + deactivation time |
medusa_emcon_duration_seconds | summary | EMCON policy time |
medusa_chunk_processed | gauge | Items processed in last chunk invocation (labeled by phase) |
medusa_chunk_queued | gauge | Items remaining in chunk queue (labeled by phase) |
medusa_serialize_duration_seconds | summary | Metrics serialization time |
medusa_track_age_at_expiry_seconds | histogram | Track age when expired |
medusa_track_updates_at_expiry | histogram | Update count when expired |
Extended metrics
Section titled “Extended metrics”Requires PrometheusExtendEnabled = true. These are per-battery and per-track metrics. They add DCS API calls per write cycle and increase the metrics file size.
| Metric | Type | Labels | Description |
|---|---|---|---|
medusa_battery_pos_x | gauge | network, battery | Battery position X |
medusa_battery_pos_z | gauge | network, battery | Battery position Z |
medusa_battery_lat | gauge | network, battery | Battery latitude (WGS84) |
medusa_battery_lon | gauge | network, battery | Battery longitude (WGS84) |
medusa_battery_info | gauge | network, battery, role, status, state, target, system | Battery metadata |
medusa_battery_weapon_range_m | gauge | network, battery, weapon | Weapon max range |
medusa_battery_engagement_range_m | gauge | network, battery, system | Current engagement range |
medusa_battery_shots_fired | gauge | network, battery | Per-battery shots fired |
medusa_battery_ammo | gauge | network, battery | Per-battery ammo remaining |
medusa_battery_cluster_lat | gauge | network, battery, cluster | Launcher cluster latitude (only for distributed groups) |
medusa_battery_cluster_lon | gauge | network, battery, cluster | Launcher cluster longitude (only for distributed groups) |
medusa_battery_cluster_range_m | gauge | network, battery, cluster | Launcher cluster max weapon range (only for distributed groups) |
medusa_battery_harm_defense | gauge | network, battery, state | HARM defense state |
medusa_battery_harm_threats | gauge | network, battery | Inbound HARMs threatening battery |
medusa_battery_harm_defenders | gauge | network, battery | HARM-capable units defending |
medusa_battery_harm_ratio | gauge | network, battery | Defender to threat ratio |
medusa_battery_last_chance | gauge | network, battery, track | Last-chance salvo active |
medusa_battery_last_chance_shots_remaining | gauge | network, battery | Last-chance missiles remaining |
medusa_track_pos_x | gauge | network, track | Track position X |
medusa_track_pos_y | gauge | network, track | Track altitude |
medusa_track_pos_z | gauge | network, track | Track position Z |
medusa_track_lat | gauge | network, track | Track latitude (WGS84) |
medusa_track_lon | gauge | network, track | Track longitude (WGS84) |
medusa_track_vel_x | gauge | network, track | Track velocity X |
medusa_track_vel_y | gauge | network, track | Track velocity Y |
medusa_track_vel_z | gauge | network, track | Track velocity Z |
medusa_track_speed | gauge | network, track | Track ground speed (m/s) |
medusa_track_updates | gauge | network, track | Track update count |
medusa_track_age | gauge | network, track | Track age (seconds) |
medusa_track_harm_score | gauge | network, track | HARM likelihood score |
medusa_track_info | gauge | network, track, type, unit, identification, aircraft_type, maneuver | Track classification |
medusa_track_sprt_llr | gauge | network, track | SPRT log-likelihood ratio |
medusa_track_sprt_scans | gauge | network, track | SPRT scan count |
medusa_track_sprt_info | gauge | network, track, label | SPRT evaluation label |
medusa_track_best_pk | gauge | network, track, battery | Best Pk for track |
medusa_track_second_pk | gauge | network, track, battery | Second best Pk for track |