Skip to content

Monitoring and alerts ​

Every OpenDsec component serves Prometheus metrics and health checks. opendsecops monitor sets up node_exporter, Prometheus, Alertmanager and the alert rules. This page lists every metric and every alert, and what to do about each alert. Service level objectives and how they are computed are in SLO.

1. Endpoints ​

Every component is started with -metrics <address> (the systemd units do this) and serves there:

PathMeaning
/metricsPrometheus metrics
/healthz200 while the process is alive
/readyz200 while it can serve, else 503 with the reason (IAM without a leader, an apiserver without a cluster snapshot yet, shutting down, …)
RoleMetrics portPrometheus job
iam9461opendsec-iam
watcher9462opendsec-watcher
apiserver9463opendsec-apiserver
edge9464opendsec-edge
fleet9465opendsec-fleet
node agent9466opendsec-nodeagent
E2B gateway9467opendsec-e2b
node_exporter9100node

Load balancer health checks use the apiserver's 9463/readyz (the E2B gateway's 9467/readyz). On SIGTERM, an apiserver fails /readyz first and keeps serving 6 more seconds, so the load balancer takes it out before it stops.

2. Setup ​

sh
deploy/prod/opendsecops monitor https://alerts.example.com/hook
  • Installs node_exporter on every machine, and Prometheus (9090) and Alertmanager (9093) on the monitor node.
  • Scrape targets come from the inventory; the alert rules are deploy/monitoring/alerts.yml.
  • Alerts go out as webhooks (Alertmanager's webhook format). Without a webhook, the receiver is reset to "send nothing": before running it again, look up the existing receiver in /etc/prometheus/alertmanager.yml and pass it along.
  • Run it again after adding machines or changing roles, to scrape the new ones.

With a Prometheus of your own, add scrape targets on the ports above and load deploy/monitoring/alerts.yml.

3. Metrics ​

Every component ​

MetricTypeLabelsMeaning
opendsec_build_infogaugeversionAlways 1; the running version
opendsec_readygauge—1 while /readyz returns 200
opendsec_rpc_server_handled_totalcounterservice, method, reasonRPCs served; reason is ok or the error reason (quota_exceeded, …)
opendsec_rpc_server_handling_secondshistogramservice, methodTime to serve an RPC (streams: until they end)
opendsec_tls_cert_expiry_timestamp_secondsgaugeidentityWhen the certificates the process loaded expire (Unix time); ca is the CA
opendsec_host_mountsgauge—Entries in the process's mount table

apiserver ​

MetricTypeLabelsMeaning
opendsec_apiserver_create_secondshistogrambackend, reasonSandbox creation through the apiserver (placement, admission, edge), by outcome
opendsec_apiserver_placement_retries_totalcounterreasonCreations retried on another node after an edge rejected them, by the edge's reason
opendsec_apiserver_fork_secondshistogramheldFork time from the snapshot to the last copy; held: whether the snapshot stayed on the source node
opendsec_apiserver_move_secondshistogramreasonPaused sandboxes moved to another node

edge ​

MetricTypeLabelsMeaning
opendsec_edge_sandboxesgaugeedge, backend, stateSandboxes per state
opendsec_edge_capacitygaugeedge, resourceSchedulable capacity (overcommit applied): cpu_cores, memory_mb, gpus, disk_mb
opendsec_edge_allocatedgaugeedge, resourceResources allocated to sandboxes
opendsec_edge_mem_available_mbgaugeedgeThe node's MemAvailable
opendsec_edge_disk_available_mbgaugeedgeFree space on the state directory's file system
opendsec_edge_under_pressuregaugeedge, pressure1 while creations are rejected under memory, disk or CPU pressure
opendsec_edge_draininggaugeedge1 while draining (no new sandboxes)
opendsec_edge_moved_ingaugeedgeSandboxes that moved here from another node
opendsec_edge_created_totalcounteredgeSandboxes created
opendsec_edge_rejected_totalcounteredgeCreations rejected (no capacity, draining, pressure)
opendsec_edge_create_secondshistogrambackend, reasonCreation on the node (admission to running)
opendsec_edge_create_phase_secondshistogrambackend, phaseCreation phases (prepare, network, config, start, …), to find what is slow
opendsec_edge_op_secondshistogrambackend, op, reasonPause, resume, stop, snapshot
opendsec_edge_runtime_infogaugeedge, component, versionVersions of the runtime programs the node uses (e.g. firecracker)
opendsec_snapshot_transfer_secondshistogramkindSnapshots moved between nodes: fetched from another edge, pulled from or published to the store
opendsec_snapshot_transfer_bytes_totalcounterkindSnapshot data received from other edges (holes and zero runs excluded)

IAM and watcher ​

MetricMeaning
opendsec_iam_leader1 on the IAM replica that leads
opendsec_iam_leasesQuota leases held (one per live sandbox)
opendsec_iam_backup_last_success_timestamp_secondsLast successful IAM backup (from the backup script, through node_exporter's textfile collector)
opendsec_watcher_edges_healthyEdges answering
opendsec_watcher_edges_unhealthyEdges not answering
opendsec_watcher_edges_drainingEdges draining

fleet (on the leader only) ​

MetricLabelsMeaning
opendsec_fleet_leaderreplica1 on the leading replica
opendsec_fleet_nodesstate, domainMachines per state and failure domain
opendsec_fleet_node_releasereleaseMachines per running release
opendsec_fleet_heartbeat_age_seconds—Age of the oldest heartbeat among active machines
opendsec_fleet_rollout_activestate1 while a rollout is in this state
opendsec_fleet_rollout_progress—Share of the active rollout's steps done

Useful queries ​

promql
# creations per second, by outcome
sum by (reason) (rate(opendsec_apiserver_create_seconds_count[5m]))

# p99 creation time, by backend
histogram_quantile(0.99, sum by (le, backend) (rate(opendsec_apiserver_create_seconds_bucket[5m])))

# server-side error ratio (caller errors such as quota and bad arguments excluded)
sum(rate(opendsec_rpc_server_handled_total{reason=~"internal|unavailable|timeout"}[5m]))
  / sum(rate(opendsec_rpc_server_handled_total[5m]))

# running sandboxes per node and backend
sum by (edge, backend) (opendsec_edge_sandboxes{state="RUNNING"})

# share of memory allocated
sum(opendsec_edge_allocated{resource="memory_mb"}) / sum(opendsec_edge_capacity{resource="memory_mb"})

# which creation phase is slow
histogram_quantile(0.99, sum by (le, phase) (rate(opendsec_edge_create_phase_seconds_bucket{backend="microvm"}[10m])))

# versions running
count by (version) (opendsec_build_info)

4. Alerts ​

The rules are in deploy/monitoring/alerts.yml, 25 of them. Severities: critical needs action now, warning the same day, info is worth a look.

Control plane ​

AlertSeverityForMeaningWhat to do
OpenDsecComponentDowncritical1mPrometheus cannot scrape a componentopendsecops status; on that machine, systemctl status <unit> and journalctl -u <unit>
OpenDsecComponentNotReadycritical2mA component reports not readycurl <ip>:<port>/readyz returns the reason
OpenDsecIAMNoLeadercritical30sIAM has no leader: creations and authentication failAre fewer than 2 IAM replicas up? Is port 7011 open between them?
OpenDsecIAMQuorumAtRiskwarning2mFewer than 3 IAM replicas up; one more failure loses the quorumBring the replica back soon; do not maintain another IAM node meanwhile
OpenDsecWatcherDegradedwarning2mFewer than 2 watchers upBring the watcher back
OpenDsecAPIServerDegradedwarning2mFewer than 2 apiservers readyBring the apiserver back; check the load balancer's health checks
OpenDsecCertExpiringSoonwarning1hA certificate expires within 30 daysRenew it: operations manual §4, "Certificates"
OpenDsecIAMBackupStalewarning—No successful IAM backup for 36 hourssystemctl status opendsec-iam-backup; check /var/backups/opendsec and disk space
OpenDsecVersionSkewinfo2hMore than one version running for over 2 hoursAn upgrade that stopped halfway? opendsecctl fleet rollout status

Sandboxes ​

AlertSeverityForMeaningWhat to do
OpenDsecEdgeUnhealthycritical1mEdges not answering the watchers; their quota is released after lost_edge_graceIs the machine up and opendsec-edge running?
OpenDsecCreateErrorscritical5mToo many creations fail for server-side reasonsBreak opendsec_apiserver_create_seconds down by reason; check edge logs
OpenDsecCreateSlowwarning10mp99 creation time of a backend is too highFind the slow phase with opendsec_edge_create_phase_seconds; check the image store and node disks
OpenDsecEdgeUnderPressurewarning5mAn edge rejects creations under memory, disk or CPU pressureSee the pressure label; free resources, add capacity or lower quotas
OpenDsecCapacityLowwarning15mMost of the cluster's sandbox memory is allocatedAdd compute nodes or lower quotas
OpenDsecEdgeDiskLowwarning10mAn edge's state file system has under 10% freeClean up; look for many snapshots or large sandbox disks
NodeFilesystemAlmostFullwarning10mA file system on a node is almost fullWhich mount point: logs, audit logs, state directory?
NodeImageStoreMissingcritical5mAn edge node does not have the image store mountedmount /mnt/opendsec-images on it; check the NAS

fleet ​

AlertSeverityForMeaningWhat to do
OpenDsecFleetNoLeaderwarning1mNo fleet replica leads: no heartbeats are taken and rollouts stand still (components keep running)Check the fleet replicas and IAM
OpenDsecFleetNodeSilentwarning2mA node agent has not reported for a whileopendsecctl fleet nodes shows which; systemctl status opendsec-nodeagent
OpenDsecFleetRolloutPausedwarning30mA rollout has been paused for 30 minutesopendsecctl fleet rollout status -steps for the reason, then resume, roll back or abort
OpenDsecFleetDriftinfo10mMachines run different releases while no rollout is activePinned machines, or one out of sync: fleet node sync <name>

SLO ​

AlertSeverityForMeaning
OpenDsecSLOCreateBurnFastcritical2mCreation errors burn the error budget 14.4x too fast: 2 days of this spend the 30-day budget
OpenDsecSLOCreateBurnSlowwarning15m6x: 5 days spend it
OpenDsecSLORuntimeBurnFastcritical2mRuntime calls (commands, files, stop, pause, resume, fork), 14.4x
OpenDsecSLORuntimeBurnSlowwarning15mAs above, 6x

What to do: break the errors down by reason and method and find when they started; was there a release, a config change or a node failure at that time? How the SLOs are computed: SLO.

5. Logs ​

WhatWhere
Component logsjournald: journalctl -u opendsec-edge, journalctl -u 'opendsec-apiserver@*', …
Warnings and errors onlyjournalctl -u 'opendsec-*' -p warning --since -1h
Audit logaudit_dir on apiserver nodes (default /var/log/opendsec/audit), JSON lines, one per call: time, principal, method, project, sandbox, outcome, latency, source address. Commands are recorded as their length and SHA-256 only
IAM backups/var/backups/opendsec on IAM nodes

Log levels are set with each component's -log flag (debug, info, warn, error); the default is info.

Under systemd each log line starts with its syslog priority (such as <4>), which journald records as the entry's priority, so -p warning finds the warnings and errors. Builds from before 2026-10-25 lack the prefix and log everything at the normal priority: use journalctl -u 'opendsec-*' --since -1h | grep -E 'level=(WARN|ERROR)'.

Implements the paper DeepSeek Elastic Compute (DSec) (arXiv:2609.22978). An independent project, not affiliated with DeepSeek.