Appearance
Logs in launches
By default, a test report contains no log output — your tests' console logs live in CI, not in the report files that get uploaded to Sulu. So if your tests log plenty but a launch's Logs panel is empty, that's expected until you turn on one of the two options below.
| You want | Use | Granularity | Setup |
|---|---|---|---|
| The whole run's console in the launch — any language | suluctl watch | launch-level | none — on by default |
| Per-test logs under each result | suluctl init | per test result | none for pytest / Playwright; one-time scaffold for Java |
Both rely on the suluctl CLI — install it first.
Whole-run console — watch
The simplest path, and it works for any language or framework. Run your tests throughsuluctl watch (rather than uploading the results afterwards) so suluctl can capture the console:
bash
suluctl watch --results ./allure-results -- mvn test
# also: ./gradlew test · pytest · npx playwright test · dotnet test · …The run's stdout and stderr appear in the launch's Logs panel (stdout as INFO, stderr as ERROR). This is on by default.
- Disable it with
SULU_SHIP_CONSOLE=false(or the--ship-console=falseflag). - Capture is best-effort — if Sulu is unreachable it never affects your test command's exit code.
- Capped at ~50 MB / 200k lines per run (see Default settings).
⚠️ Don't print secrets. Console shipping sends all stdout/stderr to Sulu — don't print tokens, credentials, or PII in tests, or turn it off with
SULU_SHIP_CONSOLE=false.
These logs are launch-scoped — the whole run's console, shown at the launch level rather than under an individual test result. For logs under each result, see below.
Per-test logs — suluctl init
To show logs under each individual test result (the result's own Logs tab), the test framework has to attach them while the test runs. Where that isn't automatic, suluctl init wires it up:
bash
suluctl init # detects your logging framework → scaffolds the log
# glue, then prints the XML snippet to register it
suluctl watch --results ./build/allure-results -- ./gradlew testWhat's supported
| Stack | Per-test logs | What you do |
|---|---|---|
pytest (allure-pytest) | ✅ automatic | nothing — captured logging is attached for you |
Playwright (allure-playwright) | ✅ automatic | nothing — captured stdout is attached for you |
| Java + log4j2 | ✅ via suluctl init | paste the printed snippet into log4j2.xml |
| Java + logback | ✅ via suluctl init (needs a suluctl newer than v0.4.0) | paste the printed snippet into logback-test.xml |
| Java + JUL, xUnit / .NET | ❌ not yet | use the whole-run watch path above |
Using logback?
Logback detection is newer than the v0.4.0 release — update suluctl if suluctl init tells you to add log4j2 instead of offering the logback snippet.
For the two Java paths, init scaffolds a small log appender plus a per-test flush and prints the exact registration snippet to paste — suluctl never edits your logging config for you:
- log4j2 — a
<SuluLog>appender plus a<Configuration packages="…">block inlog4j2.xml. - logback — an
<appender name="SuluLog" class="…SuluLogAppender">with an<encoder>pattern, plus an<appender-ref ref="SuluLog"/>inside<root>, inlogback-test.xml. logback resolves appenders by class name, so there is nopackages="…"equivalent to set.
If your Java build declares neither, init says so and tells you which dependency to add.
Logs still not showing?
Run through
watch, not a bareupload— onlywatchcan capture the console.For per-test logs, check the appender is registered:
- log4j2 —
<SuluLog>is inlog4j2.xmland<Configuration>carriespackages="<your glue package>"; without it log4j2 can't find the appender. - logback — the
<appender class="…SuluLogAppender">is inlogback-test.xmland an<appender-ref ref="SuluLog"/>sits inside<root>; an appender that nothing references never receives events.
- log4j2 —
initskipped the appender? It reads your build file, so a logging framework pulled in only as a transitive dependency is invisible to it. Declare it as an explicit test dependency and re-runsuluctl init --force.A hand-written integration must match the routing contract — the scaffolded glue does this automatically. Sulu treats a result attachment as a log when both hold:
- the attachment name is
log,logs,stdout, orstderr, optionally suffixed.txtor.log(case-insensitive) — e.g.log,stdout.txt,logs.log; - its MIME type is exactly
text/plain.
Anything else stays a regular attachment and won't appear in the result's Logs tab.
- the attachment name is