Hi all! We had an incident and I'm wondering why ...
# community-support
r
Hi all! We had an incident and I'm wondering why the volume anomaly did not fire. (on multiple tables downstream as well, with sharp dropoffs). I imagine my settings must be incorrect, but I'd like to get them fixed so we catch this issue next time. example of the drastic drop:
The last row_count value is 6244. The average for this metric is 67110.786.
We got less than 10% of the normal amount of data. I have this on the model:
Copy code
tests:
      - elementary.volume_anomalies:
          timestamp_column: page_view_time
          seasonality: day_of_week
and this at the project level, under vars:
Copy code
training_period:
    period: day
    count: 90
  seasonality: day_of_week
  detection_period:
    period: day
    count: 2
  detection_delay:   # <https://docs.elementary-data.com/data-tests/anomaly-detection-configuration/detection-delay>
    period: day
    count: 1         # we don't want to alert on "today" because it's partial
Any ideas on what I should set to ensure we get alerted? The range of values is upper 60k-lower 70ks every day, so there's not a wild variation on the daily volume normally.
Elementary is the latest version 0.13.2 The data was low for a couple days before someone noticed it in a report, it wasn't "today" / partial day.
d
Hey @Renee Cooper, At first sight the configuration looks fine. Can you share a screenshot of the graph of this test from the report ?
I'm suspecting the seasonality variable, but not 100% sure
r
We want day-of-week because we have variation -- generally Sat/Sun are lower counts than the rest of the week.
Note that I've backfilled the data and we've run dbt & elementary since then; not sure if that affects how this looks now.
d
@Renee Cooper I meant the graph from the test results screen, which shows the metrics
r
There are no other graphs but that one. So far as I know Elementary still has the anomaly bug where there are never any graphs -- it always shows "Not enough data to calculate anomaly score" despite having years of data and only a 90 day (or less) lookback. I've asked about this and been told it's a bug and will be fixed soon. If that's incorrect, lmk. It's true for all anomaly tests of all kinds: freshness, volume, and dimensional.
d
@Renee Cooper can you refer me to your previous threads regarding this ?
a
hi both, i'm debugging a similar incident and my current hypothesis is that the detection_period is part of the training_period, which dilutes the training_stddev, and and therefore makes it less sensitive. could this be the case? at least in my case i can manually replicate the anomaly score when including the detection period. FYI: i can also report that i'm seeing the "Not enough data to calculate anomaly score" in the report.
i think i found the responsible lines in the code as well, shouldn't it be
between unbounded preceeding and 1 preceding
in these windows here?
c
Hi team, how are you? I’m facing the same issue, and I was wondering if this is something you intend to address? I believe the change mentioned above would fix the issue 🙌
j
Hi Caterina, could you please share your test configuration and a screenshot of the report?
c
Sure! We had an anomaly on 08/02, but it didn't trigger any alert. The row_count was stable during the entire training period leading up to it. However, because the incident day is included in the training data, its value ends up being considered “normal” for that day — which I don’t think should be the case.
Copy code
models:
  - name: gold_ess_ingest
    data_tests:
      - elementary.schema_changes:
          severity: warn
      - elementary.volume_anomalies:
          fail_on_zero: true
    config:
      elementary:
        ignore_small_changes:
          spike_failure_percent_threshold: 1
        detection_delay:
          count: 1
          period: day
        time_bucket:
          count: 1
          period: day
        timestamp_column: partition_date
        where_expression: DATE(partition_date) > DATE_SUB(CURRENT_DATE(), INTERVAL
          14 DAY)
version: 2
j
Thanks! Can I ask the reason is for having the detection delay of one day?
c
Because of the nature of the source really. The data refreshes with one day delay
Thought I mention this too: I also tried this hack, with
anomaly_exclude_metrics
, but I found that this configuration excludes that date not only from the training period, but the whole detection period as well - the datapoint is removed from the report.
j
Ok will have a look, and do you also have the report generated on 08/02? Would be interesting to see what the graph looked like on that day
Thanks for all the extra info
c
I don't think I have it 🤔
j
It's a little hard to debug it, also because of the
ignore_small_changes
. I don't think in this case it is because of the detection period being part of the training period, but I would expect that this was anamolous on 08/02. Not sure if you are currently hosting the edr report, but if you do, it might be nice to store and retain the last 7 days so we can debug these cases.
c
I’m wondering how it could be flagged as anomalous if it’s within the expected range.. are those expected values showing correctly in the report? Since
ignore_small_changes
is set to 1% and the drop was much larger, I’m not sure how it might have influenced
j
The expected range you see now is adjusted because it now includes the anomalous value. However, my expectation is that on 08/02 it would have been an anomaly. You are right on the
ignore_small_changes
because I see you only have set the spike threshold (and also it's just 1%)
c
Do you know if there’s a way to exclude this kind of anomalies from the training period?
j
Because we need to be able to store the data on when to exclude
c
Hi again @Joost Boonzajer Flaes blob wave I could reproduce the issue with this sample - I'm hoping with this, it's easier to debug 🙏 `test_model.sql`:
Copy code
{{ config(materialized="table") }}

with
    thresholds as (
        select *
        from
            (
                values
                    ('2025-08-14'::date, 10),
                    ('2025-08-15'::date, 12),
                    ('2025-08-16'::date, 12),
                    ('2025-08-17'::date, 13),
                    ('2025-08-18'::date, 10),
                    ('2025-08-19'::date, 12),
                    ('2025-08-20'::date, 10),
                    ('2025-08-21'::date, 11),
                    ('2025-08-22'::date, 9),
                    ('2025-08-23'::date, 8),
                    ('2025-08-24'::date, 10),
                    ('2025-08-25'::date, 12),
                    ('2025-08-26'::date, 12),
                    ('2025-08-27'::date, 12),
                    ('2025-08-28'::date, 12),
                    ('2025-08-29'::date, 12),
                    ('2025-08-30'::date, 20),
                    ('2025-08-31'::date, 12),
                    ('2025-09-01'::date, 10)
            ) as t(partition_date, max_value)
    )

select t.partition_date, g.value
from thresholds t
cross join lateral generate_series(1, t.max_value) as g(value)
and the schema:
Copy code
version: 2

models:
  - name: test_model
    columns:
      - name: partition_date
        data_type: DATE
        data_tests:
          - elementary.column_anomalies:
              anomaly_direction: spike
              column_anomalies:
                - null_percent
      - name: value
        data_type: FLOAT64
    data_tests:
      - elementary.volume_anomalies:
          fail_on_zero: true
    config:
      elementary:
        time_bucket:
          count: 1
          period: day
        detection_delay:
          count: 1
          period: day
        timestamp_column: partition_date
Even though the row_count is 20 and almost doubles the avg, it's not considered anomalous, because the value 20 is included in the expected range calculation: