Skip to main content

潜龙 — a passive, semantic anomaly-detection sentinel for system events and logs.

Project description

trace-sentinel

Passive anomaly detection for logs and system events.

trace-sentinel learns a baseline from your event stream and surfaces only what genuinely deviates from it — both statistically (online z-score / MAD) and semantically (log lines whose content is new, not just whose numbers are large). It's a zero-dependency Python library and CLI, with an optional live dashboard.

It is a building block, not a platform: embed it in an app, a job runner, or a pipeline, and route the anomalies wherever you already send alerts.

Features

  • Streaming and passive — feed events one at a time; baselines update in O(1) with no batch jobs and no stored history.
  • Statistical + semantic — z-score/EWMA and robust median/MAD for magnitudes, plus a semantic-novelty detector for unfamiliar content — both expressed in the same sigma units, so one threshold governs everything.
  • Calm by default — a 3σ default, outlier-resistant detectors, and baseline seeding so it isn't noisy from a cold start.
  • Zero dependencies — pure standard-library core, Python 3.9+. Optional extras only if you bring real vector embeddings.
  • Composable — write your own extractors, swap detectors, and send anomalies to any sink (console, JSON lines, webhook, your SIEM).
  • Batteries included — a trace-sentinel CLI and a trace-sentinel-hud live dashboard.

Install

pip install trace-sentinel

# optional extras
pip install "trace-sentinel[embeddings]"   # numpy, for custom vector embeddings
pip install "trace-sentinel[dev]"          # pytest, ruff, mypy

Python 3.9+. The core has no third-party dependencies.

Quickstart

from trace_sentinel import Sentinel, Event

sentinel = Sentinel(threshold=3.0, warmup=30, enable_semantic=True)

for line in open("app.log"):
    for anomaly in sentinel.observe(Event.from_line(line, source="app")):
        print(anomaly.severity.value, anomaly.explanation)

observe() returns the anomalies for that event (usually none). Nothing fires during warmup or for values inside the learned baseline.

CLI

trace-sentinel watch app.log --semantic                       # plain text log
trace-sentinel watch events.jsonl --jsonl --format json       # JSON lines -> JSON out
trace-sentinel watch /var/log/auth.log --follow --semantic    # tail -f a live file
trace-sentinel watch app.log --semantic --seed 3000           # prime baselines first

Live dashboard

trace-sentinel-hud        # streams your real system logs to http://localhost:8787

A self-contained HUD (threat gauge, σ-timeline, per-metric rings, scrolling anomaly feed) driven entirely by real engine state — no simulated data.

How it works

                 ┌───────────┐   features    ┌────────────┐   sigma   ┌──────────┐
 Event  ───────▶ │ Extractors│ ────────────▶ │  Detectors │ ────────▶ │ Sentinel │ ──▶ Anomaly
 (log line)      └───────────┘ message.length└────────────┘ z / MAD   │ threshold│      (+ Sink)
                       │       message.tokens                          └──────────┘
                       │            ...                                      ▲
                       └────────── message text ───▶ Semantic novelty ──────┘
  1. Extractors turn each Event into named numeric metrics (message.length, message.tokens, numeric fields, inter-arrival time, …).
  2. Detectors keep one online baseline per metric and return a standardized deviation in sigma. A value is scored against history before it's folded in, so a spike is measured against the past, not against itself.
  3. The Sentinel emits an Anomaly when |score| ≥ threshold, after a per-metric warmup.
  4. The semantic layer embeds the message text, tracks a decaying centroid of "normal," and scores novelty — standardized to sigma so it thresholds exactly like the numeric metrics.

Cold baselines over-alert, so Sentinel.prime() (and the bundled benign-signal corpus in trace_sentinel.seed) can establish a stable "normal" up front. See docs/concepts.md.

Roadmap

Stage Capability Status
Detect passive statistical + semantic detection (this release) ✅ 0.1
Correlate cross-source correlation, alert routing, dashboards planned
Respond automated response / playbooks planned

Documentation

Doc Contents
Quickstart Install and first run
Concepts The detection model, sigma, and the 2σ caveat
Detectors Z-score, EWMA drift, robust MAD
Semantic layer Novelty scoring; plugging in real embeddings / LLMs
Extractors Built-ins and writing your own
CLI trace-sentinel watch reference
API reference Public classes and functions
Production Tuning, persistence, scaling, gotchas
FAQ How it compares to SIEM/UEBA

Development

pip install -e ".[dev]"
pytest            # test suite
ruff check .      # lint
mypy              # type-check (strict)

License

MIT © 2026 Ken Li. See LICENSE.

Also published under the name 潜龙 (qiánlóng, “hidden dragon”) — dormant until something genuinely stirs it.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

trace_sentinel-0.2.0.tar.gz (60.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

trace_sentinel-0.2.0-py3-none-any.whl (43.4 kB view details)

Uploaded Python 3

File details

Details for the file trace_sentinel-0.2.0.tar.gz.

File metadata

  • Download URL: trace_sentinel-0.2.0.tar.gz
  • Upload date:
  • Size: 60.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for trace_sentinel-0.2.0.tar.gz
Algorithm Hash digest
SHA256 d770353946c76f1538600bfd3eb13bfca7e53e55b47497b0163c9daba15f9a7e
MD5 9daa6f32c65f7c410dbad8aaf227a93b
BLAKE2b-256 748b10551dec14b1b27f83b5faa01585042cc375568ad2e9a2a704a559523276

See more details on using hashes here.

File details

Details for the file trace_sentinel-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: trace_sentinel-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 43.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for trace_sentinel-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 21f9dd7642f79638f1b988f91a8e8b13d756cb6e842d6bf0066961cb6fc138b5
MD5 49d63bb54826edc7cd2514b6ea60ac4a
BLAKE2b-256 cd733998a8b7c88b8d24ab5d452c65e7c887faf1badc181035cf0130f2d42c95

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page