Skip to main content

hazure

You have a metric — requests per second, queue depth, a sensor reading — you suspect it occasionally misbehaves, and you have no record of when it did. hazure finds those moments: rule-based and unsupervised detectors that learn what "normal" looks like from the series itself, and that say where it stopped holding.

Any pandas, polars or pyarrow object with a time axis goes in, and the answer comes back in the same flavour. At runtime it needs narwhals and numpy and nothing else; every heavier dependency is an extra, imported lazily by the algorithm that needs it.

pip install hazure[pandas]
import numpy as np
import pandas as pd
from hazure.detection import SeasonalDetector
from hazure.events import to_events

# Hourly traffic with a daily rhythm — and one afternoon that went wrong.
rng = np.random.default_rng(0)
index = pd.date_range("2024-03-01", periods=24 * 21, freq="h", name="time")
daily = 40 * np.sin(2 * np.pi * np.arange(len(index)) / 24)
traffic = pd.Series(100 + daily + rng.normal(0, 3, len(index)), index=index, name="rps")
traffic.iloc[300:306] = 20.0

labels = SeasonalDetector(period=24).fit_detect(traffic)
print(to_events(labels))
# Events([2024-03-13T12:00:00..2024-03-13T17:59:59.999999999])

labels sits on traffic's own index — 1.0 anomalous, 0.0 normal, NaN unknown — and the six flagged hours are exactly the six that were planted.

Everything is one of five composable component types (Scorer, Threshold, Detector, Aggregator, Transformer), chained with Pipeline and wired with Graph when the model branches.

On a series that is still arriving

Fit once on a period you are willing to call normal, then feed observations in as they come. Stream runs the same fitted component over a buffer of recent history, so the online answer is the batch answer rather than a second implementation of it — and prime refuses to start if the buffer is too short for what the component looks back over, instead of quietly computing from a window that was never full.

from hazure import Stream

detector = SeasonalDetector(period=24).fit(traffic)
stream = Stream(detector, history=48).prime(traffic)

stream.update("2024-03-22T00:00", 105.0)  # in line with the fortnight -> 0.0
stream.update("2024-03-22T01:00", 12.0)  # not in line with it -> 1.0

Where to draw the line

Every threshold is parameterised by something, and none of those somethings is "the answer I want". Two ways to get one. PotThreshold takes the false-alarm probability directly — it fits a generalised Pareto to the tail of the training scores, so the fence can be placed where exceedance has probability 1e-4, beyond the largest score ever observed. And budget_threshold needs no labels at all: give it the number of alerts a week anyone will read, and it lowers the fence as far as that allows and no further.

Documentation

https://ykus4.github.io/hazure/

  • Quickstart — one planted anomaly end to end: detect, convert to intervals, score, plot.
  • Guide — which detector suits which kind of anomaly, and the two behaviours that surprise people most.
  • How it works — the mathematics of every scorer, threshold and metric, and where each one's assumptions run out.
  • API reference — every public name.

Details

  • Python 3.11 and newer.
  • Fully typed; mypy --strict clean.
  • MIT licensed.

Download files

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

Source Distribution

hazure-0.1.0.tar.gz (929.7 kB view details)

Uploaded Source

Built Distribution

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

hazure-0.1.0-py3-none-any.whl (247.8 kB view details)

Uploaded Python 3

File details

Details for the file hazure-0.1.0.tar.gz.

File metadata

  • Download URL: hazure-0.1.0.tar.gz
  • Upload date:
  • Size: 929.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for hazure-0.1.0.tar.gz
Algorithm Hash digest
SHA256 49a700eeec538bc78aff4bad8dc99fd00373091d37b303021dfbba7da4266a1c
MD5 5ffc756ef760d4db36e8613850807d1b
BLAKE2b-256 cb8d729cf182c1c50db5568d9df1c884980827bfd68a931d5c234027bc40b442

See more details on using hashes here.

Provenance

The following attestation bundles were made for hazure-0.1.0.tar.gz:

Publisher: release.yml on ykus4/hazure

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hazure-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: hazure-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 247.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for hazure-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 70db3f86683401d4689287e2b510480ca18b6349ad7428b29aa5efcb84fbd318
MD5 d306d1bb9b5dd86d7511623df2317b5e
BLAKE2b-256 7ce3789b8cca383a9375817d8193063209a8ef967fc8b359b68533b3c4e784fe

See more details on using hashes here.

Provenance

The following attestation bundles were made for hazure-0.1.0-py3-none-any.whl:

Publisher: release.yml on ykus4/hazure

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page