TH2.4 series_fir() and Time Series Smoothing
Noise hides patterns
When you run make-series on sign-in data with hourly bins, the raw values fluctuate. Some hours have 5 sign-ins, the next has 0, the next has 8. Visually and statistically, this noise obscures whether the overall level has increased, decreased, or stayed the same over days or weeks.
A moving average smooths the series by replacing each data point with the average of itself and its neighbors. A 24-hour moving average on hourly data replaces each hour’s value with the average of the surrounding 24 hours — revealing the daily trend while eliminating hourly fluctuations.
Moving average with series_fir()
| |
The filter array dynamic([1,1,1,1,1,1,1]) defines a 7-point equal-weight moving average. Each element contributes equally. For a weighted moving average that emphasizes recent data, use decreasing weights: dynamic([1,2,3,4,3,2,1]) — the central point and its immediate neighbors are weighted more heavily than distant points.
Hunting application: detecting sustained behavioral shifts
| |
The difference between this and TH2.3 (anomaly detection): series_decompose_anomalies() finds individual data points that spike. series_fir() smoothing reveals sustained shifts in the overall level. Both are useful. Anomaly detection catches acute events (a single day of massive downloads). Smoothing catches gradual changes (download volume slowly increasing over two weeks as an attacker methodically exfiltrates data).
Figure TH2.4 — Raw versus smoothed time series. Noise in the raw data obscures a clear upward trend that the 7-day moving average reveals.
Try it yourself
Exercise: Smooth your sign-in data
Run the 7-day moving average query against your organization-wide sign-in data (single series, not per-user). Add `| render timechart` to visualize.
Observe: is the smoothed line flat, trending up, or trending down? A flat smoothed line means stable activity. An upward trend during a period when no new users were onboarded could indicate increased automated activity (legitimate or malicious). A downward trend during business-as-usual could indicate a data ingestion problem.
The myth: Smoothing filters destroy information. Analysis should always use raw data to ensure nothing is missed.
The reality: Smoothing does not remove data — it separates the signal (trend, pattern) from the noise (random variation). The raw data is preserved in the original series. The smoothed series is a second view that highlights different patterns. Use raw data for acute anomaly detection (individual spikes). Use smoothed data for trend analysis (sustained behavioral shifts). Both are needed. Neither is sufficient alone.
Extend this approach
series_fir() supports custom filter designs beyond simple moving averages. An exponential weighting `dynamic([1,2,4,8,4,2,1])` emphasizes the center point more heavily. A Gaussian-like filter produces smoother output with less edge distortion. For most hunting applications, the equal-weight moving average is sufficient. Custom filters become useful when you need to distinguish between specific frequency components — for example, separating weekly business cycles from daily patterns in download volume data.
References Used in This Subsection
- Microsoft. “KQL series_fir().” Microsoft Learn. https://learn.microsoft.com/en-us/kusto/query/series-fir-function
- Course cross-references: TH2.2 (make-series), TH8 (sustained exfiltration detection), TH12 (beacon trend analysis)
You're reading the free modules of this course
The full course continues with advanced topics, production detection rules, worked investigation scenarios, and deployable artifacts. Premium subscribers get access to all courses.