Fix daily-cadence charts defaulting to sub-day time buckets (#828) (#830)

DMARC aggregate reports post one data point per reporting period
(typically daily), but several dashboard time-series panels used a
dynamically-computed bucket interval that scales with the viewed time
range/panel width instead of the data's actual cadence, producing a
spiked/gapped chart whenever that computed interval landed below a day:

- OpenSearch Dashboards: both date_histogram aggregations used
  "interval": "auto". Fixed to the "d" unit code (verified against
  OpenSearch-Dashboards' and Kibana's own _interval_options.ts /
  parse_interval.ts source — "day" is not a valid value and would throw
  at render time).
- Grafana + PostgreSQL: 7 query targets used
  $__timeGroup(col, $__interval); hardcoded to $__timeGroup(col, '1d'),
  matching the equivalent already-correct panels in the Grafana +
  Elasticsearch dashboard.
- Splunk: both `timechart` panels had no explicit span, so Splunk's
  100-bin auto-algorithm only coincidentally produced daily buckets for
  the dashboard's default 7-day view. Added span=1d per Splunk's own
  timechart documentation.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Sean Whalen
2026-07-16 20:17:57 -04:00
committed by GitHub
co-authored by Claude Sonnet 5
parent 3b53f836a6
commit 1986835f51
4 changed files with 19 additions and 11 deletions
+8
View File
@@ -1,5 +1,13 @@
# Changelog
## Unreleased
### Bug fixes
- **The "Aggregate DMARC passage over time" and "Aggregate DMARC message disposition over time" OpenSearch Dashboards visualizations no longer default to a 12-hour X-axis interval** ([#828](https://github.com/domainaware/parsedmarc/issues/828)). Both `date_histogram` aggregations were configured with `"interval": "auto"`, which OpenSearch Dashboards sizes off the currently viewed time range rather than the data's actual cadence. Aggregate DMARC reports post one `date_range`-bucketed data point per reporting period (typically daily), so an auto-computed sub-day bucket size produced empty buckets and a misleading sawtooth/spike pattern. Both visualizations in `dashboards/opensearch/opensearch_dashboards.ndjson` now hardcode `"interval": "d"`, matching the fix the reporter applied manually in the visualization editor (the "Day" option in the interval picker). Per OpenSearch-Dashboards' `_interval_options.ts` and `parse_interval.ts` (`src/plugins/data/common/search/aggs/...`), the stored `interval` value must be a short duration-unit code (`ms`/`s`/`m`/`h`/`d`/`w`/`M`/`y`) or the literal `auto`; a spelled-out word like `"day"` fails `parseInterval`'s regex and throws `"day" is not a valid interval.` at render time, so `"d"` is required, not `"day"`.
- **The same auto-interval time-bucketing bug from #828 also affected the PostgreSQL Grafana dashboard's "Over Time" panels** (`dashboards/grafana/Grafana-DMARC_Reports-PostgreSQL.json`): "SPF Results Over Time", "DKIM Results Over Time", "DMARC Pass/Fail Over Time", "Disposition Over Time", "SMTP TLS Sessions Over Time", and one unlabeled summary `stat` panel all grouped rows with `$__timeGroup(<column>, $__interval)`, where `$__interval` is a Grafana-computed value that scales with the panel's pixel width and the selected time range, not the reports' actual daily cadence (per the Grafana PostgreSQL query-editor macro docs). All 7 occurrences now hardcode the bucket width to `'1d'` (`$__timeGroup(rpt.begin_date, '1d')` / `$__timeGroup(tr.begin_date, '1d')`), matching the `fixed_interval: "1d"` already used by the equivalent panels in the companion Elasticsearch/Grafana dashboard (`Grafana-DMARC_Reports.json`), which was already correct and needed no change. The Elasticsearch/Grafana dashboard's non-time-series pie/stat/table panels that still use a `date_histogram` with `"fixed_interval": "auto"` were left as-is: they sum every bucket into a single value or list raw hits, so the bucket width has no visible effect there.
- **The same bug also affected the Splunk "DMARC passage over time" and "Message disposition over time" panels** (`dashboards/splunk/dmarc_aggregate_dashboard.xml`). Both `| timechart` calls had no explicit `span`, so Splunk auto-computes a bin size targeting 100 buckets across whatever time range is selected; per Splunk's `timechart` documentation this only coincidentally lands on a 1-day span for the dashboard's default "last 7 days" time-range input; any other selected range (e.g. "last 24 hours" → 30 minutes) reproduces the same gapped/spiked chart. Both queries now set `span=1d` explicitly, per the Splunk docs' own guidance to use `span=1d` (not `span=24h`/`span=86400s`/`span=1440m`) for calendar-day boundaries.
## 10.2.3
### Changes
@@ -407,7 +407,7 @@
},
"editorMode": "code",
"format": "time_series",
"rawSql": "SELECT\n $__timeGroup(rpt.begin_date, $__interval) AS time,\n COALESCE(spf.result, 'none') AS metric,\n SUM(r.message_count) AS value\nFROM dmarc_aggregate_record r\nJOIN dmarc_aggregate_report rpt ON rpt.id = r.report_id\nLEFT JOIN dmarc_aggregate_record_spf spf ON spf.record_id = r.id\nWHERE $__timeFilter(rpt.begin_date)\n AND r.header_from IN ($fromdomain)\nGROUP BY time, spf.result\nORDER BY time",
"rawSql": "SELECT\n $__timeGroup(rpt.begin_date, '1d') AS time,\n COALESCE(spf.result, 'none') AS metric,\n SUM(r.message_count) AS value\nFROM dmarc_aggregate_record r\nJOIN dmarc_aggregate_report rpt ON rpt.id = r.report_id\nLEFT JOIN dmarc_aggregate_record_spf spf ON spf.record_id = r.id\nWHERE $__timeFilter(rpt.begin_date)\n AND r.header_from IN ($fromdomain)\nGROUP BY time, spf.result\nORDER BY time",
"refId": "A"
}
]
@@ -477,7 +477,7 @@
},
"editorMode": "code",
"format": "time_series",
"rawSql": "SELECT\n $__timeGroup(rpt.begin_date, $__interval) AS time,\n COALESCE(dkim.result, 'none') AS metric,\n SUM(r.message_count) AS value\nFROM dmarc_aggregate_record r\nJOIN dmarc_aggregate_report rpt ON rpt.id = r.report_id\nLEFT JOIN dmarc_aggregate_record_dkim dkim ON dkim.record_id = r.id\nWHERE $__timeFilter(rpt.begin_date)\n AND r.header_from IN ($fromdomain)\nGROUP BY time, dkim.result\nORDER BY time",
"rawSql": "SELECT\n $__timeGroup(rpt.begin_date, '1d') AS time,\n COALESCE(dkim.result, 'none') AS metric,\n SUM(r.message_count) AS value\nFROM dmarc_aggregate_record r\nJOIN dmarc_aggregate_report rpt ON rpt.id = r.report_id\nLEFT JOIN dmarc_aggregate_record_dkim dkim ON dkim.record_id = r.id\nWHERE $__timeFilter(rpt.begin_date)\n AND r.header_from IN ($fromdomain)\nGROUP BY time, dkim.result\nORDER BY time",
"refId": "A"
}
]
@@ -547,7 +547,7 @@
},
"editorMode": "code",
"format": "time_series",
"rawSql": "SELECT\n $__timeGroup(rpt.begin_date, $__interval) AS time,\n CASE WHEN r.dmarc_passed THEN 'true' ELSE 'false' END AS metric,\n SUM(r.message_count) AS value\nFROM dmarc_aggregate_record r\nJOIN dmarc_aggregate_report rpt ON rpt.id = r.report_id\nWHERE $__timeFilter(rpt.begin_date)\n AND r.header_from IN ($fromdomain)\nGROUP BY time, r.dmarc_passed\nORDER BY time",
"rawSql": "SELECT\n $__timeGroup(rpt.begin_date, '1d') AS time,\n CASE WHEN r.dmarc_passed THEN 'true' ELSE 'false' END AS metric,\n SUM(r.message_count) AS value\nFROM dmarc_aggregate_record r\nJOIN dmarc_aggregate_report rpt ON rpt.id = r.report_id\nWHERE $__timeFilter(rpt.begin_date)\n AND r.header_from IN ($fromdomain)\nGROUP BY time, r.dmarc_passed\nORDER BY time",
"refId": "A"
}
]
@@ -626,7 +626,7 @@
},
"editorMode": "code",
"format": "time_series",
"rawSql": "SELECT\n $__timeGroup(rpt.begin_date, $__interval) AS time,\n COALESCE(r.disposition, 'unknown') AS metric,\n SUM(r.message_count) AS value\nFROM dmarc_aggregate_record r\nJOIN dmarc_aggregate_report rpt ON rpt.id = r.report_id\nWHERE $__timeFilter(rpt.begin_date)\n AND r.header_from IN ($fromdomain)\nGROUP BY time, r.disposition\nORDER BY time",
"rawSql": "SELECT\n $__timeGroup(rpt.begin_date, '1d') AS time,\n COALESCE(r.disposition, 'unknown') AS metric,\n SUM(r.message_count) AS value\nFROM dmarc_aggregate_record r\nJOIN dmarc_aggregate_report rpt ON rpt.id = r.report_id\nWHERE $__timeFilter(rpt.begin_date)\n AND r.header_from IN ($fromdomain)\nGROUP BY time, r.disposition\nORDER BY time",
"refId": "A"
}
]
@@ -675,7 +675,7 @@
},
"editorMode": "code",
"format": "time_series",
"rawSql": "SELECT\n $__timeGroup(rpt.begin_date, $__interval) AS time,\n SUM(r.message_count) AS value\nFROM dmarc_aggregate_record r\nJOIN dmarc_aggregate_report rpt ON rpt.id = r.report_id\nWHERE $__timeFilter(rpt.begin_date)\n AND r.header_from IN ($fromdomain)\nGROUP BY time\nORDER BY time",
"rawSql": "SELECT\n $__timeGroup(rpt.begin_date, '1d') AS time,\n SUM(r.message_count) AS value\nFROM dmarc_aggregate_record r\nJOIN dmarc_aggregate_report rpt ON rpt.id = r.report_id\nWHERE $__timeFilter(rpt.begin_date)\n AND r.header_from IN ($fromdomain)\nGROUP BY time\nORDER BY time",
"refId": "A"
}
]
@@ -1592,7 +1592,7 @@
},
"editorMode": "code",
"format": "time_series",
"rawSql": "SELECT\n $__timeGroup(tr.begin_date, $__interval) AS time,\n 'Successful' AS metric,\n SUM(p.successful_session_count) AS value\nFROM smtp_tls_report tr\nJOIN smtp_tls_policy p ON p.report_id = tr.id\nWHERE $__timeFilter(tr.begin_date)\nGROUP BY time\nORDER BY time",
"rawSql": "SELECT\n $__timeGroup(tr.begin_date, '1d') AS time,\n 'Successful' AS metric,\n SUM(p.successful_session_count) AS value\nFROM smtp_tls_report tr\nJOIN smtp_tls_policy p ON p.report_id = tr.id\nWHERE $__timeFilter(tr.begin_date)\nGROUP BY time\nORDER BY time",
"refId": "A"
},
{
@@ -1602,7 +1602,7 @@
},
"editorMode": "code",
"format": "time_series",
"rawSql": "SELECT\n $__timeGroup(tr.begin_date, $__interval) AS time,\n 'Failed' AS metric,\n SUM(p.failed_session_count) AS value\nFROM smtp_tls_report tr\nJOIN smtp_tls_policy p ON p.report_id = tr.id\nWHERE $__timeFilter(tr.begin_date)\nGROUP BY time\nORDER BY time",
"rawSql": "SELECT\n $__timeGroup(tr.begin_date, '1d') AS time,\n 'Failed' AS metric,\n SUM(p.failed_session_count) AS value\nFROM smtp_tls_report tr\nJOIN smtp_tls_policy p ON p.report_id = tr.id\nWHERE $__timeFilter(tr.begin_date)\nGROUP BY time\nORDER BY time",
"refId": "B"
}
]
@@ -11,8 +11,8 @@
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Aggregate DMARC message volume by header from","uiStateJSON":"{}","version":1,"visState":"{\"title\": \"Aggregate DMARC message volume by header from\", \"type\": \"table\", \"aggs\": [{\"id\": \"1\", \"enabled\": true, \"type\": \"sum\", \"params\": {\"field\": \"message_count\", \"customLabel\": \"messages\"}, \"schema\": \"metric\"}, {\"id\": \"2\", \"enabled\": true, \"type\": \"terms\", \"params\": {\"field\": \"header_from.keyword\", \"orderBy\": \"1\", \"order\": \"desc\", \"size\": 10000, \"otherBucket\": false, \"otherBucketLabel\": \"Other\", \"missingBucket\": false, \"missingBucketLabel\": \"Missing\", \"customLabel\": \"header_from\"}, \"schema\": \"bucket\"}], \"params\": {\"perPage\": 10, \"percentageCol\": \"\", \"showMetricsAtAllLevels\": false, \"showPartialRows\": false, \"showTotal\": false, \"totalFunc\": \"sum\"}}"},"id":"2c929eb0-2633-11f1-96a6-fb3734bd0b21","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"e1143020-2628-11f1-96a6-fb3734bd0b21","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2026-05-21T20:33:15.708Z","version":"WzEwLDFd"}
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Aggregate DMARC message sources by name and type","uiStateJSON":"{}","version":1,"visState":"{\"title\": \"Aggregate DMARC message sources by name and type\", \"type\": \"table\", \"aggs\": [{\"id\": \"1\", \"enabled\": true, \"type\": \"sum\", \"params\": {\"field\": \"message_count\", \"customLabel\": \"messages\"}, \"schema\": \"metric\"}, {\"id\": \"2\", \"enabled\": true, \"type\": \"terms\", \"params\": {\"field\": \"source_name.keyword\", \"orderBy\": \"1\", \"order\": \"desc\", \"size\": 10000, \"otherBucket\": false, \"otherBucketLabel\": \"Other\", \"missingBucket\": true, \"missingBucketLabel\": \"none\", \"customLabel\": \"source_name\"}, \"schema\": \"bucket\"}, {\"id\": \"3\", \"enabled\": true, \"type\": \"terms\", \"params\": {\"field\": \"source_type.keyword\", \"orderBy\": \"1\", \"order\": \"desc\", \"size\": 2000, \"otherBucket\": false, \"otherBucketLabel\": \"Other\", \"missingBucket\": true, \"missingBucketLabel\": \"none\", \"customLabel\": \"source_type\"}, \"schema\": \"bucket\"}], \"params\": {\"perPage\": 10, \"showPartialRows\": false, \"showMetricsAtAllLevels\": false, \"showTotal\": false, \"totalFunc\": \"sum\", \"percentageCol\": \"\"}}"},"id":"81380390-2635-11f1-96a6-fb3734bd0b21","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"e1143020-2628-11f1-96a6-fb3734bd0b21","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2026-05-21T20:33:15.708Z","version":"WzExLDFd"}
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Aggregate DMARC message sources by Autonomous System","uiStateJSON":"{}","version":1,"visState":"{\"title\": \"Aggregate DMARC message sources by Autonomous System\", \"type\": \"table\", \"aggs\": [{\"id\": \"1\", \"enabled\": true, \"type\": \"sum\", \"params\": {\"field\": \"message_count\", \"customLabel\": \"messages\"}, \"schema\": \"metric\"}, {\"id\": \"2\", \"enabled\": true, \"type\": \"terms\", \"params\": {\"field\": \"source_asn\", \"orderBy\": \"1\", \"order\": \"desc\", \"size\": 10000, \"otherBucket\": false, \"otherBucketLabel\": \"Other\", \"missingBucket\": false, \"missingBucketLabel\": \"Missing\", \"customLabel\": \"asn\"}, \"schema\": \"bucket\"}, {\"id\": \"3\", \"enabled\": true, \"type\": \"terms\", \"params\": {\"field\": \"source_as_name.keyword\", \"orderBy\": \"1\", \"order\": \"desc\", \"size\": 10000, \"otherBucket\": false, \"otherBucketLabel\": \"Other\", \"missingBucket\": true, \"missingBucketLabel\": \"\", \"customLabel\": \"as_name\"}, \"schema\": \"bucket\"}, {\"id\": \"4\", \"enabled\": true, \"type\": \"terms\", \"params\": {\"field\": \"source_as_domain.keyword\", \"orderBy\": \"1\", \"order\": \"desc\", \"size\": 10000, \"otherBucket\": false, \"otherBucketLabel\": \"Other\", \"missingBucket\": true, \"missingBucketLabel\": \"\", \"customLabel\": \"as_domain\"}, \"schema\": \"bucket\"}], \"params\": {\"perPage\": 10, \"showPartialRows\": false, \"showMetricsAtAllLevels\": false, \"showTotal\": false, \"totalFunc\": \"sum\", \"percentageCol\": \"\"}}"},"id":"adec76e0-3f68-11f1-a327-dd68bf273446","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"e1143020-2628-11f1-96a6-fb3734bd0b21","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2026-05-21T20:33:15.708Z","version":"WzEyLDFd"}
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Aggregate DMARC passage over time","uiStateJSON":"{\"vis\":{\"colors\":{\"false\":\"#e7664c\",\"true\":\"#54b399\"}}}","version":1,"visState":"{\"title\": \"Aggregate DMARC passage over time\", \"type\": \"line\", \"aggs\": [{\"id\": \"1\", \"enabled\": true, \"type\": \"sum\", \"params\": {\"field\": \"message_count\", \"customLabel\": \"messages\"}, \"schema\": \"metric\"}, {\"id\": \"2\", \"enabled\": true, \"type\": \"date_histogram\", \"params\": {\"field\": \"date_range\", \"timeRange\": {\"from\": \"now-7d\", \"to\": \"now\"}, \"useNormalizedOpenSearchInterval\": true, \"scaleMetricValues\": false, \"interval\": \"auto\", \"drop_partials\": false, \"min_doc_count\": 1, \"extended_bounds\": {}}, \"schema\": \"segment\"}, {\"id\": \"3\", \"enabled\": true, \"type\": \"terms\", \"params\": {\"field\": \"passed_dmarc\", \"orderBy\": \"1\", \"order\": \"desc\", \"size\": 5, \"otherBucket\": false, \"otherBucketLabel\": \"Other\", \"missingBucket\": false, \"missingBucketLabel\": \"Missing\"}, \"schema\": \"group\"}], \"params\": {\"type\": \"line\", \"grid\": {\"categoryLines\": false}, \"categoryAxes\": [{\"id\": \"CategoryAxis-1\", \"type\": \"category\", \"position\": \"bottom\", \"show\": true, \"style\": {}, \"scale\": {\"type\": \"linear\"}, \"labels\": {\"show\": true, \"filter\": true, \"truncate\": 100}, \"title\": {}}], \"valueAxes\": [{\"id\": \"ValueAxis-1\", \"name\": \"LeftAxis-1\", \"type\": \"value\", \"position\": \"left\", \"show\": true, \"style\": {}, \"scale\": {\"type\": \"linear\", \"mode\": \"normal\"}, \"labels\": {\"show\": true, \"rotate\": 0, \"filter\": false, \"truncate\": 100}, \"title\": {\"text\": \"Sum of message_count\"}}], \"seriesParams\": [{\"show\": true, \"type\": \"line\", \"mode\": \"normal\", \"data\": {\"label\": \"Sum of message_count\", \"id\": \"1\"}, \"valueAxis\": \"ValueAxis-1\", \"drawLinesBetweenPoints\": true, \"lineWidth\": 2, \"interpolate\": \"linear\", \"showCircles\": true}], \"addTooltip\": true, \"addLegend\": true, \"legendPosition\": \"right\", \"times\": [], \"addTimeMarker\": false, \"labels\": {}, \"thresholdLine\": {\"show\": false, \"value\": 10, \"width\": 1, \"style\": \"full\", \"color\": \"#E7664C\"}, \"row\": true}}"},"id":"0b277550-263a-11f1-96a6-fb3734bd0b21","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"e1143020-2628-11f1-96a6-fb3734bd0b21","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2026-05-21T20:33:15.708Z","version":"WzEzLDFd"}
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Aggregate DMARC message disposition over time","uiStateJSON":"{\"vis\":{\"colors\":{\"false\":\"#e7664c\",\"none\":\"#54b399\",\"quarantine\":\"#d6bf57\",\"reject\":\"#e7664c\",\"true\":\"#54b399\"}}}","version":1,"visState":"{\"title\": \"Aggregate DMARC message disposition over time\", \"type\": \"line\", \"aggs\": [{\"id\": \"1\", \"enabled\": true, \"type\": \"sum\", \"params\": {\"field\": \"message_count\", \"customLabel\": \"messages\"}, \"schema\": \"metric\"}, {\"id\": \"2\", \"enabled\": true, \"type\": \"date_histogram\", \"params\": {\"field\": \"date_range\", \"timeRange\": {\"from\": \"now-7d\", \"to\": \"now\"}, \"useNormalizedOpenSearchInterval\": true, \"scaleMetricValues\": false, \"interval\": \"auto\", \"drop_partials\": false, \"min_doc_count\": 1, \"extended_bounds\": {}}, \"schema\": \"segment\"}, {\"id\": \"3\", \"enabled\": true, \"type\": \"terms\", \"params\": {\"field\": \"disposition.keyword\", \"orderBy\": \"1\", \"order\": \"desc\", \"size\": 10, \"otherBucket\": false, \"otherBucketLabel\": \"Other\", \"missingBucket\": true, \"missingBucketLabel\": \"missing\"}, \"schema\": \"group\"}], \"params\": {\"addLegend\": true, \"addTimeMarker\": false, \"addTooltip\": true, \"categoryAxes\": [{\"id\": \"CategoryAxis-1\", \"labels\": {\"filter\": true, \"show\": true, \"truncate\": 100}, \"position\": \"bottom\", \"scale\": {\"type\": \"linear\"}, \"show\": true, \"style\": {}, \"title\": {}, \"type\": \"category\"}], \"grid\": {\"categoryLines\": false}, \"labels\": {}, \"legendPosition\": \"right\", \"row\": true, \"seriesParams\": [{\"data\": {\"id\": \"1\", \"label\": \"Sum of message_count\"}, \"drawLinesBetweenPoints\": true, \"interpolate\": \"linear\", \"lineWidth\": 2, \"mode\": \"normal\", \"show\": true, \"showCircles\": true, \"type\": \"line\", \"valueAxis\": \"ValueAxis-1\"}], \"thresholdLine\": {\"color\": \"#E7664C\", \"show\": false, \"style\": \"full\", \"value\": 10, \"width\": 1}, \"times\": [], \"type\": \"line\", \"valueAxes\": [{\"id\": \"ValueAxis-1\", \"labels\": {\"filter\": false, \"rotate\": 0, \"show\": true, \"truncate\": 100}, \"name\": \"LeftAxis-1\", \"position\": \"left\", \"scale\": {\"mode\": \"normal\", \"type\": \"linear\"}, \"show\": true, \"style\": {}, \"title\": {\"text\": \"Sum of message_count\"}, \"type\": \"value\"}]}}"},"id":"d4545010-263a-11f1-96a6-fb3734bd0b21","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"e1143020-2628-11f1-96a6-fb3734bd0b21","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2026-05-21T20:33:15.708Z","version":"WzE0LDFd"}
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Aggregate DMARC passage over time","uiStateJSON":"{\"vis\":{\"colors\":{\"false\":\"#e7664c\",\"true\":\"#54b399\"}}}","version":1,"visState":"{\"title\": \"Aggregate DMARC passage over time\", \"type\": \"line\", \"aggs\": [{\"id\": \"1\", \"enabled\": true, \"type\": \"sum\", \"params\": {\"field\": \"message_count\", \"customLabel\": \"messages\"}, \"schema\": \"metric\"}, {\"id\": \"2\", \"enabled\": true, \"type\": \"date_histogram\", \"params\": {\"field\": \"date_range\", \"timeRange\": {\"from\": \"now-7d\", \"to\": \"now\"}, \"useNormalizedOpenSearchInterval\": true, \"scaleMetricValues\": false, \"interval\": \"d\", \"drop_partials\": false, \"min_doc_count\": 1, \"extended_bounds\": {}}, \"schema\": \"segment\"}, {\"id\": \"3\", \"enabled\": true, \"type\": \"terms\", \"params\": {\"field\": \"passed_dmarc\", \"orderBy\": \"1\", \"order\": \"desc\", \"size\": 5, \"otherBucket\": false, \"otherBucketLabel\": \"Other\", \"missingBucket\": false, \"missingBucketLabel\": \"Missing\"}, \"schema\": \"group\"}], \"params\": {\"type\": \"line\", \"grid\": {\"categoryLines\": false}, \"categoryAxes\": [{\"id\": \"CategoryAxis-1\", \"type\": \"category\", \"position\": \"bottom\", \"show\": true, \"style\": {}, \"scale\": {\"type\": \"linear\"}, \"labels\": {\"show\": true, \"filter\": true, \"truncate\": 100}, \"title\": {}}], \"valueAxes\": [{\"id\": \"ValueAxis-1\", \"name\": \"LeftAxis-1\", \"type\": \"value\", \"position\": \"left\", \"show\": true, \"style\": {}, \"scale\": {\"type\": \"linear\", \"mode\": \"normal\"}, \"labels\": {\"show\": true, \"rotate\": 0, \"filter\": false, \"truncate\": 100}, \"title\": {\"text\": \"Sum of message_count\"}}], \"seriesParams\": [{\"show\": true, \"type\": \"line\", \"mode\": \"normal\", \"data\": {\"label\": \"Sum of message_count\", \"id\": \"1\"}, \"valueAxis\": \"ValueAxis-1\", \"drawLinesBetweenPoints\": true, \"lineWidth\": 2, \"interpolate\": \"linear\", \"showCircles\": true}], \"addTooltip\": true, \"addLegend\": true, \"legendPosition\": \"right\", \"times\": [], \"addTimeMarker\": false, \"labels\": {}, \"thresholdLine\": {\"show\": false, \"value\": 10, \"width\": 1, \"style\": \"full\", \"color\": \"#E7664C\"}, \"row\": true}}"},"id":"0b277550-263a-11f1-96a6-fb3734bd0b21","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"e1143020-2628-11f1-96a6-fb3734bd0b21","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2026-05-21T20:33:15.708Z","version":"WzEzLDFd"}
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"language\":\"kuery\",\"query\":\"\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Aggregate DMARC message disposition over time","uiStateJSON":"{\"vis\":{\"colors\":{\"false\":\"#e7664c\",\"none\":\"#54b399\",\"quarantine\":\"#d6bf57\",\"reject\":\"#e7664c\",\"true\":\"#54b399\"}}}","version":1,"visState":"{\"title\": \"Aggregate DMARC message disposition over time\", \"type\": \"line\", \"aggs\": [{\"id\": \"1\", \"enabled\": true, \"type\": \"sum\", \"params\": {\"field\": \"message_count\", \"customLabel\": \"messages\"}, \"schema\": \"metric\"}, {\"id\": \"2\", \"enabled\": true, \"type\": \"date_histogram\", \"params\": {\"field\": \"date_range\", \"timeRange\": {\"from\": \"now-7d\", \"to\": \"now\"}, \"useNormalizedOpenSearchInterval\": true, \"scaleMetricValues\": false, \"interval\": \"d\", \"drop_partials\": false, \"min_doc_count\": 1, \"extended_bounds\": {}}, \"schema\": \"segment\"}, {\"id\": \"3\", \"enabled\": true, \"type\": \"terms\", \"params\": {\"field\": \"disposition.keyword\", \"orderBy\": \"1\", \"order\": \"desc\", \"size\": 10, \"otherBucket\": false, \"otherBucketLabel\": \"Other\", \"missingBucket\": true, \"missingBucketLabel\": \"missing\"}, \"schema\": \"group\"}], \"params\": {\"addLegend\": true, \"addTimeMarker\": false, \"addTooltip\": true, \"categoryAxes\": [{\"id\": \"CategoryAxis-1\", \"labels\": {\"filter\": true, \"show\": true, \"truncate\": 100}, \"position\": \"bottom\", \"scale\": {\"type\": \"linear\"}, \"show\": true, \"style\": {}, \"title\": {}, \"type\": \"category\"}], \"grid\": {\"categoryLines\": false}, \"labels\": {}, \"legendPosition\": \"right\", \"row\": true, \"seriesParams\": [{\"data\": {\"id\": \"1\", \"label\": \"Sum of message_count\"}, \"drawLinesBetweenPoints\": true, \"interpolate\": \"linear\", \"lineWidth\": 2, \"mode\": \"normal\", \"show\": true, \"showCircles\": true, \"type\": \"line\", \"valueAxis\": \"ValueAxis-1\"}], \"thresholdLine\": {\"color\": \"#E7664C\", \"show\": false, \"style\": \"full\", \"value\": 10, \"width\": 1}, \"times\": [], \"type\": \"line\", \"valueAxes\": [{\"id\": \"ValueAxis-1\", \"labels\": {\"filter\": false, \"rotate\": 0, \"show\": true, \"truncate\": 100}, \"name\": \"LeftAxis-1\", \"position\": \"left\", \"scale\": {\"mode\": \"normal\", \"type\": \"linear\"}, \"show\": true, \"style\": {}, \"title\": {\"text\": \"Sum of message_count\"}, \"type\": \"value\"}]}}"},"id":"d4545010-263a-11f1-96a6-fb3734bd0b21","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"e1143020-2628-11f1-96a6-fb3734bd0b21","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2026-05-21T20:33:15.708Z","version":"WzE0LDFd"}
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Aggregate DMARC map of message sources by country","uiStateJSON":"{}","version":1,"visState":"{\"title\": \"Aggregate DMARC map of message sources by country\", \"type\": \"region_map\", \"aggs\": [{\"id\": \"1\", \"enabled\": true, \"type\": \"sum\", \"params\": {\"field\": \"message_count\", \"customLabel\": \"messages\"}, \"schema\": \"metric\"}, {\"id\": \"2\", \"enabled\": true, \"type\": \"terms\", \"params\": {\"field\": \"source_country.keyword\", \"orderBy\": \"1\", \"order\": \"desc\", \"size\": 500, \"otherBucket\": false, \"otherBucketLabel\": \"Other\", \"missingBucket\": false, \"missingBucketLabel\": \"Missing\"}, \"schema\": \"segment\"}], \"params\": {\"addTooltip\": true, \"colorSchema\": \"Yellow to Red\", \"emsHotLink\": \"?locale=en#file/world_countries\", \"isDisplayWarning\": true, \"layerChosenByUser\": \"default\", \"legendPosition\": \"bottomright\", \"mapCenter\": [0, 0], \"mapZoom\": 2, \"outlineWeight\": 1, \"selectedCustomJoinField\": null, \"selectedJoinField\": {\"description\": \"ISO 3166-1 alpha-2 Code\", \"name\": \"iso2\", \"type\": \"id\"}, \"selectedLayer\": {\"attribution\": \"<a rel=\\\"noreferrer noopener\\\" href=\\\"http://www.naturalearthdata.com/about/terms-of-use\\\">Made with NaturalEarth</a>\", \"created_at\": \"2017-04-26T17:12:15.978370\", \"fields\": [{\"description\": \"ISO 3166-1 alpha-2 Code\", \"name\": \"iso2\", \"type\": \"id\"}, {\"description\": \"ISO 3166-1 alpha-3 Code\", \"name\": \"iso3\", \"type\": \"id\"}, {\"description\": \"Name\", \"name\": \"name\", \"type\": \"name\"}], \"format\": {\"type\": \"geojson\"}, \"id\": \"world_countries\", \"isEMS\": true, \"layerId\": \"elastic_maps_service.World Countries\", \"name\": \"World Countries\", \"origin\": \"elastic_maps_service\"}, \"showAllShapes\": true, \"wms\": {\"enabled\": false, \"options\": {\"attribution\": \"\", \"format\": \"image/png\", \"layers\": \"\", \"styles\": \"\", \"transparent\": true, \"version\": \"\"}, \"selectedTmsLayer\": {\"attribution\": \"<a rel=\\\"noreferrer noopener\\\" href=\\\"https://www.openstreetmap.org/copyright\\\">Map data \\u00a9 OpenStreetMap contributors</a>\", \"id\": \"road_map\", \"maxZoom\": 14, \"minZoom\": 0, \"origin\": \"elastic_maps_service\"}, \"url\": \"\"}}}"},"id":"bf2bfba0-263c-11f1-96a6-fb3734bd0b21","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"e1143020-2628-11f1-96a6-fb3734bd0b21","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2026-05-21T20:33:15.708Z","version":"WzE1LDFd"}
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Aggregate DMARC message sources by country","uiStateJSON":"{}","version":1,"visState":"{\"title\": \"Aggregate DMARC message sources by country\", \"type\": \"table\", \"aggs\": [{\"id\": \"1\", \"enabled\": true, \"type\": \"sum\", \"params\": {\"field\": \"message_count\", \"customLabel\": \"messages\"}, \"schema\": \"metric\"}, {\"id\": \"2\", \"enabled\": true, \"type\": \"terms\", \"params\": {\"field\": \"source_country.keyword\", \"orderBy\": \"1\", \"order\": \"desc\", \"size\": 500, \"otherBucket\": false, \"otherBucketLabel\": \"Other\", \"missingBucket\": true, \"missingBucketLabel\": \"unknown\", \"customLabel\": \"source_country\"}, \"schema\": \"bucket\"}], \"params\": {\"perPage\": 10, \"showPartialRows\": false, \"showMetricsAtAllLevels\": false, \"showTotal\": false, \"totalFunc\": \"sum\", \"percentageCol\": \"\"}}"},"id":"0bcd9900-263d-11f1-96a6-fb3734bd0b21","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"e1143020-2628-11f1-96a6-fb3734bd0b21","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2026-05-21T20:33:15.708Z","version":"WzE2LDFd"}
{"attributes":{"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[],\"indexRefName\":\"kibanaSavedObjectMeta.searchSourceJSON.index\"}"},"title":"Aggregate DMARC message sources by IP address","uiStateJSON":"{}","version":1,"visState":"{\"title\":\"Aggregate DMARC message sources by IP address\",\"type\":\"table\",\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"sum\",\"params\":{\"field\":\"message_count\",\"customLabel\":\"messages\"},\"schema\":\"metric\"},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"source_ip_address.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":10000,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":false,\"missingBucketLabel\":\"Missing\",\"customLabel\":\"ip_address\"},\"schema\":\"bucket\"},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"source_reverse_dns.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":10000,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":true,\"missingBucketLabel\":\"none\",\"customLabel\":\"reverse_dns\"},\"schema\":\"bucket\"},{\"id\":\"4\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"source_base_domain.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":10000,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":true,\"missingBucketLabel\":\"none\",\"customLabel\":\"reverse_dns_base_domain\"},\"schema\":\"bucket\"},{\"id\":\"5\",\"enabled\":true,\"type\":\"terms\",\"params\":{\"field\":\"source_country.keyword\",\"orderBy\":\"1\",\"order\":\"desc\",\"size\":10000,\"otherBucket\":false,\"otherBucketLabel\":\"Other\",\"missingBucket\":true,\"missingBucketLabel\":\"unknown\",\"customLabel\":\"country\"},\"schema\":\"bucket\"}],\"params\":{\"perPage\":10,\"showPartialRows\":false,\"showMetricsAtAllLevels\":false,\"showTotal\":false,\"totalFunc\":\"sum\",\"percentageCol\":\"\"}}"},"id":"a8143340-263e-11f1-96a6-fb3734bd0b21","migrationVersion":{"visualization":"7.10.0"},"references":[{"id":"e1143020-2628-11f1-96a6-fb3734bd0b21","name":"kibanaSavedObjectMeta.searchSourceJSON.index","type":"index-pattern"}],"type":"visualization","updated_at":"2026-05-21T20:33:15.708Z","version":"WzE3LDFd"}
@@ -238,7 +238,7 @@
<title>DMARC passage over time</title>
<chart>
<search base="base_search">
<query>| timechart sum(message_count) as message_count by passed_dmarc</query>
<query>| timechart span=1d sum(message_count) as message_count by passed_dmarc</query>
</search>
<option name="charting.axisTitleX.text">Time</option>
<option name="charting.axisTitleX.visibility">visible</option>
@@ -259,7 +259,7 @@
<title>Message disposition over time</title>
<chart>
<search base="base_search">
<query>| timechart sum(message_count) as message_count by disposition</query>
<query>| timechart span=1d sum(message_count) as message_count by disposition</query>
</search>
<option name="charting.axisTitleX.text">Time</option>
<option name="charting.axisTitleY.text">Messages</option>