Entity risk score¶
LogMan.io uses two related risk score concepts:
| Concept | Where | Meaning |
|---|---|---|
| Detection risk score | event.risk_score on complex lane events |
Numeric score of one detection after correlation rules and lookups (see Risk scoring in Correlator) |
| Entity risk score | risk_score on the asset row in Mongo / HTTP API |
Current risk of the principal (user, host, service), decaying when no new detections arrive |
This page documents the entity risk score maintained by LogMan.io Assets (lmio-assets).
Input: complex lane events¶
ComplexAssetsPipeline subscribes to each tenant complex event lane declaration (/EventLanes/<tenant>/complex.yaml, type lmio/event-lane-complex). The Kafka topic defaults to events.<tenant>.complex unless overridden in the lane YAML.
For each event that contains the schema risk score field (define.risk_score, default event.risk_score) and at least one principal (host.id, user.id, or service.id from the schema mapping), the service records a sample:
- Contribution: parsed detection risk value (positive numbers only)
- Event time: Unix ms from the schema principal datetime field (
define.principal_datetime, e.g.@timestamp)
Samples are buffered and flushed to Mongo in event time order (same batching knobs as activity: complex_mongo_batch_max, complex_mongo_batch_max_age).
Merged or deleted asset _ids are ignored (shared suppress cache with activity processing).
Decay model¶
The stored entity score is a time decayed weighted average of detection event.risk_score values. Recent detections matter more; old ones fade but still influence the average until they decay away.
Internal Mongo accumulators:
risk_score_sum(S): weighted sum of detection valuesrisk_score_weight(W): effective sample weightrisk_score:round(S / W)exposed in the API
Between updates, both S and W decay with half life (default 24h):
S ← S × decay(Δt)
W ← W × decay(Δt)
When a detection with value c arrives at event time t:
S ← S × decay(Δt) + c
W ← W × decay(Δt) + 1
score = S / W
| Symbol | Meaning |
|---|---|
c |
event.risk_score on the complex lane detection |
Δt |
Elapsed time since risk_score_at → event time |
decay(Δt) |
0.5 ** (Δt_hours / half_life_hours) |
Why not a sum? Ten low detections over a week should not stack to an extreme entity score. The average moves toward new c values; stale history loses weight exponentially.
Example: score was 80 (one detection). A new detection c = 20 arrives immediately: S = 80 + 20, W = 2, score 50 (not 100). After 24h silence, both S and W halve, score stays 50. Then c = 60: score becomes 55.
Mongo stores:
risk_score: rounded average (round(S / W))risk_score_sum/risk_score_weight: internal accumulators (not in public JSON)risk_score_at: Unix ms of the last update clock (not exposed in public JSON)
Scores that decay below risk_score_decay_clear_below (default 0.5) are cleared from API responses and removed on the passive decay job.
Late arriving events¶
If an event timestamp is before risk_score_at, its value is blended into the average, but risk_score_at is not moved backward.
Passive decay job¶
On Application.tick/600! (same cadence as stale asset alerting), the service persists passive decay for all assets with risk_score > 0 so list sort (srisk_score) stays aligned with the model.
Between ticks, GET, list, and export still apply decay at read time so the API shows the effective score now.
Per asset risk score weight (lookup API)¶
The HTTP API exposes /risk-score-weight endpoints to read, set, or clear an optional override in LogMan.io Watcher lookups (hostid2riskscore, userid2riskscore, serviceid2riskscore). The lookup key is the asset title (principal id); the value field is risk.score (0..100).
This is separate from the decay merge logic: entity score still grows from event.risk_score on consumed complex events. Use the weight API when your deployment wires these lookups into detection scoring or analyst workflows.
Webui: stored field vs chart¶
In lmio_asset_webui asset detail, two views are intentional:
| View | What it shows |
|---|---|
risk_score in list / sidebar |
Entity state now (decayed score) |
| Risk score line chart | Detection activity over time: max(risk_field) per histogram bucket over complex lane events only (event.dataset = complex), single series (no split by rule.id) |
The chart answers: “What was the peak detection risk score for this principal in each time window?”
The stored field answers: “How risky is this entity right now, accounting for decay?”
Configuration¶
[assets] key |
Default | Description |
|---|---|---|
risk_score_decay_half_life |
24h |
Half life for exponential decay (ASAB duration syntax) |
risk_score_decay_clear_below |
0.5 |
Clear score when decayed value falls below this |
complex_mongo_batch_max |
100 |
Buffered detections before Mongo flush |
complex_mongo_batch_max_age |
60 |
Max seconds before partial risk buffer flush |
See Configuration for the full [assets] section and service dependencies.