Indexes, Exclusion Filters, and Retention
The idea in one sentence
Section titled “The idea in one sentence”A log can be dropped or filtered at three genuinely different stages — on the host before it ever leaves, or at an index’s daily quota, or by an index’s own Exclusion Filter — and each of those has different cost and recoverability implications, so they must not be conflated.
Stage 1: Agent-side exclude_at_match
Section titled “Stage 1: Agent-side exclude_at_match”Before a log ever leaves the host, the Agent itself can drop it via a log_processing_rules entry with type exclude_at_match, matching a regex pattern against the raw log line.
logs: - type: file path: /my/app/file.log service: payments-api source: java log_processing_rules: - type: exclude_at_match name: exclude_healthcheck_lines pattern: 'GET /healthz'This is the cheapest possible place to filter, because a dropped line never consumes network, intake, or storage — but it is also final. A log excluded here is gone forever: it is not archived, it does not reach a Processing Pipeline, and it cannot be recovered later. Only use this for genuinely worthless lines (health-check noise, debug spam you never want in any form), because there is no undo.
Stage 2: Log Indexes — retention_days and daily_limit
Section titled “Stage 2: Log Indexes — retention_days and daily_limit”Logs that survive the Agent and pass through intake and a Processing Pipeline arrive at one or more Log Indexes. An index is where full-price, searchable retention actually happens, and each index configures two numbers that matter for cost and behavior:
{ "name": "main", "daily_limit": 100, "retention_days": 30, "exclusion_filters": [ { "name": "exclude-debug", "query": "level:debug" } ]}retention_days— how long logs written into this index stay searchable in the Logs Explorer at full price.daily_limit— a GB/day quota for the index; once the quota is hit for the day, the index either stops accepting further logs or (depending on configuration) starts sampling, so a badly sizeddaily_limitcan silently cap what’s searchable regardless of anything else in your config.
An organization typically has more than one index (e.g. main for production services, a shorter-retention index for noisy or low-value logs), and which index a log lands in is itself controlled by index-level filter criteria — but the key fact for this lesson is that retention_days and daily_limit are properties of the index, not of the Agent or the pipeline.
Stage 3: Exclusion Filters — the main lever for indexed volume
Section titled “Stage 3: Exclusion Filters — the main lever for indexed volume”An Exclusion Filter lives on a specific index and uses a Lucene-style query — the same query syntax you’d type into the Logs Explorer search bar — to sample out or fully drop matching logs from being written into that index. In the config above, { "name": "exclude-debug", "query": "level:debug" } means logs matching level:debug do not get written into the main index.
This is the main day-to-day lever for controlling indexed, searchable, full-price volume, and it is deliberately more flexible and less final than Agent-side dropping:
- A log excluded from one index by its Exclusion Filter can still be routed into a different index (with different retention or cost characteristics), if your index routing sends it there.
- A log excluded from every index can still reach a Log Archive, if archiving is configured — the next lesson covers this.
- Because the exclusion happens at the index, not on the host, it can be changed centrally in Datadog without touching a single Agent config file anywhere.
Putting the order together
Section titled “Putting the order together”The full path a log takes, end to end, is: Agent collects it → an optional Agent-side exclude_at_match rule may drop some logs before they ever leave the host → surviving logs reach intake → a Processing Pipeline parses and enriches every log that matches its filter → the log reaches a Log Index, whose own Exclusion Filters decide what actually gets indexed, searchable, and billed at full price.
flowchart LR
A[Agent collects log] --> B{exclude_at_match\nmatches?}
B -->|yes, dropped forever| Z[Gone: no archive, no index]
B -->|no| C[Intake]
C --> D[Processing Pipeline\nparse + enrich]
D --> E{Index Exclusion Filter\ne.g. level:debug}
E -->|excluded| F[Not written to this index\nmay still reach archive/other index]
E -->|kept| G["Indexed: searchable\nfor retention_days, billed at full price"]