chore: reduce CI test log noise by suppressing known-structural error loggers#22905
Conversation
Adds package-level log suppressions in test log4j2 configs to hide expected ERROR messages that fire during tests (e.g. missing build.properties, apps-bundle.json, and tests exercising error paths). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use TEST_LOG_SUPPRESSED_LEVEL env var to control log4j2 suppression of expected test errors. Defaults to fatal (suppressed). The ci-verbose PR label or debug workflow dispatch sets it to error (visible). Also removes broken log.fatal() call (SLF4J has no fatal level). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
OFF is the canonical log4j2 level for disabling a logger, making the intent self-documenting rather than relying on the SLF4J/log4j2 level mismatch where FATAL works only because SLF4J has no fatal() method. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
|
|
not sure about this, some thoughts:
|
|
@david-mackessy good questions, let me address each: Default logging level is not changed. The root logger is already set to error for the console appender. I have added narrow suppressions for a small number of specific loggers on top of that baseline. Criteria for selection. : Each suppressed logger fires on passing tests due to structural facts of the test environment, not from real problems, e.g.:
Risk of hiding real errors. The suppressions use FATAL, not OFF, so genuinely catastrophic database errors still surface. The loggers are specified at class level (not broad packages), which keeps the blast radius small. Are there still errors in the logs? Yes. The root level is still at "error". Only these specific loggers are suppressed. Real errors from real failures will still appear (i.e. actual test failures). Maintenance burden. Well, its a good question, but my stance on this is once we get the CI logs down to a reasonable level, it will be much easier for developers to see if they are spewing expected errors in the logs and then either a) Add another suppression or B) Handle the echoing of expected errors in the test itself. The goal here is purely signal-to-noise: when a test actually fails in CI, the error that matters should be easy to find rather than buried in thousands of lines of expected noise. See https://github.com/dhis2/dhis2-core/actions/runs/25660816457/job/75320626269?pr=22905 for an example of what the logs look like when the unit tests pass (but the expected errors from tests are suppressed). |
|
I get the intention and frustration at trying to find meaningful, relatable error messages for tests 👍 (less noise the better). |
|
@david-mackessy Fair point on the title. "Expected test errors" implied we were filtering specific known messages, when the mechanism is actually logger-level suppression. Updated the title and description to reflect that accurately. On the "suppress all errors in scope" concern: each logger was chosen because in the test context its error output is structurally unavoidable (missing classpath resources, tests deliberately hitting error paths, etc). On a passing integration run (PR #23855) these produce 84 ERROR lines with multi-line stack traces. All noise,zero signal. For the Real test failures are not affected . JUnit/Surefire reports those independently of log4j2 config. One thing that may not be obvious: the suppression applies locally too, not just in CI. |
|



Adds targeted logger suppressions in test log4j2 configs to reduce noise in CI run output from loggers that always fire on passing tests due to structural facts of the test environment. These are not actual test failures, but rather errors which are emitted to the logs as part of the test themselves.
Why these loggers?
Each suppressed logger fires because of a structural fact of the test environment, not a real problem:
BundledAppManager/DefaultSystemService:apps-bundle.jsonandbuild.propertiesare absent from the test classpath by design.JdbcAnalyticsManager/DataHandler: analytics tables do not exist in thetest database; tests that exercise ADEX code paths produce expected
"relation does not exist" SQL errors.
SqlExceptionHelper: tests deliberately trigger uniqueness constraintviolations to verify rejection behaviour; Hibernate logs every such exception
at ERROR.
scheduling/sms/route/dxf2.gml/rules.engineetc. : teststhat verify error paths cause the application to log at ERROR. The tests pass;
the errors are the test's intent.
CrudControllerAdvice: the global@ControllerAdvicelogs at ERROR whentests deliberately exercise controller error paths (e.g. SQL injection tests).
Scoped to this class only, not the whole controller package.
Do real test failures still appear?
Yes. JUnit assertion failures and unexpected exceptions surface through Surefire
reporting, not through log4j2. The suppressions only affect the application's own
log.error(...)calls, not the test framework's failure output.Toggling verbosity
ci-verboselabel to the PR to restore full error output.TEST_LOG_SUPPRESSED_LEVEL=error mvn test ...On a passing integration test run (PR #23855, run 25673244856), this eliminates the vast majority of these "expected" errors which are nothing other than an artifact of the testing scenario.