Skip to content

Metric Types

Draft v0.1

This page is in draft. Content may change before v1.0.


Every metric row produced by an ACES-compliant connector includes a metric_type field that declares how to interpret metric_value. Because metric_value is always stored as a string, consumers must use metric_type to cast it correctly.

See also: Evidence Schema → metrics array


Type Reference

number

A numeric measurement. Cast metric_value to float or integer.

Unit examples: devices, policies, users, licenses, checks, segments, versions

Connector examples:

Connector metric_key Example value
auvik total_devices "142"
huntress agents_total "87"
sentinelone active_threats_count "3"
connectsecure total_vulns "412"
ninjarmm patches_pending "24"
msgraph total_users_licensed "55"
threatlocker total_devices "98"

percentage

A ratio expressed as a value between 0 and 100. Always paired with unit: "%". Cast metric_value to float.

Unit examples: %, percent

Connector examples:

Connector metric_key Example value
huntress agents_online_percentage "97.7"
sentinelone agent_coverage_pct "94.2"
connectsecure compliance_score_percent "78.5"
ninjarmm patch_compliance_percent "85.0"
msgraph mfa_enrollment_percent "100.0"
breachsecurenow training_completion_pct "72.3"
threatlocker denial_rate_percent "12.4"
liongard agent_health_pct "91.6"
auvik network_coverage_pct "100.0"

boolean

A true/false state. metric_value will be "true" or "false" (string). Cast to boolean.

Unit examples: none

Connector examples:

Connector metric_key Example value
msgraph audit_log_enabled "true"
msgraph legacy_auth_blocked "false"
msgraph mfa_required_by_policy "true"
msgraph mailbox_auditing_enabled "true"
msgraph devices_api_accessible "true"
msgraph location_restrictions_enabled "false"

count

A discrete integer count. Semantically distinct from number — use count when the value represents a tally of discrete events or items (incidents, denied actions, alerts). Cast to integer.

Unit examples: incidents, actions, alerts, requests, events

Connector examples:

Connector metric_key Example value
huntress incidents_critical "2"
huntress incidents_auto_resolved "14"
sentinelone threats_by_severity_critical "1"
sentinelone cve_critical_count "7"
threatlocker total_denied_actions "1842"
threatlocker pending_approvals "3"
liongard active_alert_count "0"

duration

A time span. metric_value is a numeric string representing the duration in the unit specified. Cast to float.

Unit examples: hours, minutes, seconds, ms, days

Connector examples:

Connector metric_key Unit Example value
huntress mean_time_to_detect_hours hours "4.2"
huntress mean_time_to_resolve_hours hours "18.5"
sentinelone avg_threat_resolution_hours hours "6.1"
sentinelone collection_duration_ms ms "2341"
msgraph audit_log_retention_days days "90"

datetime

An ISO 8601 timestamp string. metric_value is a timestamp — do not cast to a number. Parse as datetime.

Unit examples: none

Connector examples:

Connector metric_key Example value
auvik last_scan_date "2026-03-21T14:32:00Z"
nodeware last_scan_date "2026-03-20T09:15:00Z"
msgraph last_audit_event_at "2026-03-22T00:00:00Z"
msgraph last_exchange_audit_at "2026-03-21T18:00:00Z"
msgraph latest_alert_at "2026-03-22T06:12:00Z"
sentinelone last_collection_at "2026-03-22T12:00:00Z"
breachsecurenow last_campaign_date "2026-03-01"

json

A structured object or array, serialized as a JSON string inside metric_value. Parse metric_value with JSON.parse() before use.

Unit examples: none

Connector examples:

Connector metric_key Example value
msgraph license_types "{\"M365 Business Premium\": 42, \"E3\": 13}"
msgraph severity_distribution "{\"high\": 2, \"medium\": 5, \"low\": 1}"
msgraph os_distribution "{\"Windows 11\": 80, \"Windows 10\": 18, \"macOS\": 4}"
msgraph device_type_distribution "{\"laptop\": 85, \"desktop\": 17}"
auvik device_types_breakdown "{\"router\": 4, \"switch\": 12, \"workstation\": 98}"

string

A plain text value that does not fit another type. Use for grades, status strings, identifiers, and human-readable labels.

Unit examples: none

Connector examples:

Connector metric_key Example value
domainscanner overall_grade "B+"
domainscanner dns_security_status "pass"
domainscanner domain "acme-corp.com"
auvik last_scan_date "2026-03-21" (when no time component)
msgraph mfa_evidence_source "Microsoft Graph API"
sentinelone alerts_evidence_source "SentinelOne Management Console"
threatlocker agent_versions_unique "3" (distinct version count as label)

Type Selection Guide

Question Answer → Type
Is it a ratio of total? (X out of Y) percentage
Is it a tally of discrete events? count
Is it a continuous measurement (size, quantity)? number
Is it true or false? boolean
Is it a time span? duration
Is it a point in time? datetime
Is it a structured object/array? json
Doesn't fit any above? string

Implementation Notes

  1. Always store as string. metric_value must be a string in all serialized forms, regardless of the underlying type. This is a deliberate design decision to support heterogeneous connector outputs in a single table.

  2. Type is authoritative. Consumers must not infer type from value shape. A value of "1" could be a number, count, or boolean — always check metric_type.

  3. Unit is display-only. The unit field is for human display purposes. It does not affect how metric_value should be parsed. Parsing is always governed by metric_type.

  4. No nested types. metric_type is always a single scalar type. Use json for complex structures — do not nest ACES metric rows.