Time-Series Transforms
observability counters and gauges store only the current value — nothing
turned a counter into a per-second rate — and cost_telemetry only buckets by
a fixed day. This adds Prometheus-style rate / irate / increase /
delta (reset-aware) plus tumbling-bucket downsample and grid
resample over (timestamp, value) sequences.
Pure standard library (bisect); imports no PySide6. No wall clock is
read — windows use the series’ own timestamps — so every function is fully
deterministic in CI.
Headless API
from je_auto_control import ts_rate, ts_increase, ts_downsample, ts_resample
series = [(0, 0), (10, 50), (20, 120)] # (timestamp_s, counter_value)
ts_rate(series) # 6.0 (120 over 20s)
ts_rate(series, window_s=10) # rate over the last 10s only
ts_increase(series) # 120.0 (reset-aware)
ts_downsample([(0, 1), (3, 3), (5, 10)], 5, "avg") # [(0, 2.0), (5, 10.0)]
ts_resample([(0, 0), (20, 20)], 10, fill="linear") # [(0,0),(10,10),(20,20)]
ts_rate / ts_increase treat a value drop as a counter reset (Prometheus
semantics); ts_irate is the instant rate from the last two samples;
ts_delta / ts_idelta are gauge first-to-last and last-two differences.
ts_downsample rolls the series into bucket_s tumbling buckets aggregated
by avg / sum / min / max / first / last / count.
ts_resample aligns to a fixed grid, filling with "last" (carry forward),
"linear" (interpolate), or None (gaps).
Executor commands
AC_ts_rate returns {rate} for a series (optional window_s);
AC_ts_downsample returns {buckets} for a series and bucket_s
(optional agg). Both are exposed as MCP tools (ac_ts_rate /
ac_ts_downsample) and as Script Builder commands under Data.