plugin/errors: add show_first option to consolidate (#7702) (#7703)

Add optional show_first flag to consolidate directive that logs
the first error immediately and then consolidates subsequent errors.

When show_first is enabled:
- The first matching error is logged immediately with full details
  (rcode, domain, type, error message) using the configured log level
- Subsequent matching errors are consolidated during the period
- At period end:
  - If only one error occurred, no summary is printed (already logged)
  - If multiple errors occurred, summary shows the total count

Syntax:
  consolidate DURATION REGEXP [LEVEL] [show_first]

Example with 3 errors:
  [WARNING] 2 example.org. A: read udp 10.0.0.1:53->8.8.8.8:53: i/o timeout
  [WARNING] 3 errors like '^read udp .* i/o timeout$' occurred in last 30s

Example with 1 error:
  [WARNING] 2 example.org. A: read udp 10.0.0.1:53->8.8.8.8:53: i/o timeout

Implementation details:
- Add showFirst bool to pattern struct
- Rename inc() to consolidateError(), return false for showFirst case
- Use function pointer in ServeDNS to unify log calls with proper level
- Simplify logPattern() with single condition (cnt > 1 || !showFirst)
- Refactor parseLogLevel() to parseOptionalParams() with map-based dispatch
- Validate parameter order: log level must come before show_first
- Update README.md with show_first documentation and examples
- Add comprehensive test cases for show_first functionality

Signed-off-by: cangming <cangming@cangming.app>
This commit is contained in:
cangming
2025-12-10 10:15:49 +08:00
committed by GitHub
parent 0233f3e7c6
commit cad961f75f
5 changed files with 293 additions and 31 deletions

View File

@@ -23,7 +23,7 @@ Extra knobs are available with an expanded syntax:
~~~
errors {
stacktrace
consolidate DURATION REGEXP [LEVEL]
consolidate DURATION REGEXP [LEVEL] [show_first]
}
~~~
@@ -35,6 +35,21 @@ log level, which is configurable by optional option **LEVEL**. Supported options
2 errors like '^read udp .* i/o timeout$' occurred in last 30s
~~~
If the optional `show_first` flag is specified, the first error will be logged immediately when it occurs, and then subsequent matching errors will be consolidated. When the consolidation period ends:
- If only one error occurred, no summary is printed (since it was already logged)
- If multiple errors occurred, a summary is printed showing the total count
Example with 3 errors:
~~~
[WARNING] 2 example.org. A: read udp 10.0.0.1:53->8.8.8.8:53: i/o timeout
[WARNING] 3 errors like '^read udp .* i/o timeout$' occurred in last 30s
~~~
Example with 1 error:
~~~
[WARNING] 2 example.org. A: read udp 10.0.0.1:53->8.8.8.8:53: i/o timeout
~~~
Multiple `consolidate` options with different **DURATION** and **REGEXP** are allowed. In case if some error message corresponds to several defined regular expressions the message will be associated with the first appropriate **REGEXP**.
For better performance, it's recommended to use the `^` or `$` metacharacters in regular expression when filtering error messages by prefix or suffix, e.g. `^failed to .*`, or `.* timeout$`.
@@ -63,3 +78,16 @@ and errors with prefix "Failed to " as errors.
}
}
~~~
Use the *forward* plugin and consolidate timeout errors with `show_first` option to see both
the summary and the first occurrence of the error:
~~~ corefile
. {
forward . 8.8.8.8
errors {
consolidate 5m ".* i/o timeout$" warning show_first
consolidate 30s "^Failed to .+" error show_first
}
}
~~~