skip to content

What should a nightly JMeter job archive from a run so its results stay usable weeks later?

level: seniorimportance: should knowfreq 46%

answer

  1. Count how many files the report really is
  2. One artefact can rebuild another
  3. Something is truncated on the next run
  4. Look inside the folder before writing the glob

basics

~20 s

Archive the whole folder named by -o, not just index.html, along with the JTL results file and the run's jmeter.log. The dashboard is a directory tree of index.html, content, an sbadmin2 theme folder and statistics.json.

solid answer

~40 s

Three artefacts, and the order matters. First the **sample log** named by `-l`: it is the only re-derivable source, since a dashboard can be regenerated from a JTL but never the other way round. Second the **whole `-o` directory**: `HtmlTemplateExporter` walks `bin/report-template` and copies every file into it, so the output is `index.html` plus a `content/` directory and a bundled `sbadmin2-*` theme folder, and the default `JsonExporter` drops `statistics.json` in beside them. Archiving `index.html` on its own gives you an unstyled page with no charts. Third **`jmeter.log`**, whose shipped appender is configured with `append="false"` and is therefore truncated by the next run — if the job does not capture it per run, it is gone. Compress the report directory if your archive step charges per file; it is well over a hundred of them.

code

bash · 14 lines
bash
run="out/nightly-${BUILD_NUMBER}"
mkdir -p "$run"

jmeter -n -f -t plan.jmx \
  -l "$run/results.jtl" \
  -j "$run/jmeter.log" \
  -e -o "$run/report"

# what the report folder actually contains
ls "$run/report"
# content  index.html  sbadmin2-1.0.7  statistics.json

# archive the directory, not one file inside it
tar czf "nightly-${BUILD_NUMBER}.tgz" "$run"

go deeper

for a junior

Recall that the report produced by -o is a folder, not a single file, and that the archive step has to take the whole folder. Keep the results file named by -l as well.

for a middle

Explain what is in that folder and where it came from: a copied template tree plus statistics.json, all landing there because -o sets the report generator's output directory property.

for a senior

Show you have been burned. Name the three artefacts, say which can be regenerated from which, and note that jmeter.log is truncated each run so it must be captured or renamed per run.

for a principal

Own retention across the estate: how long a sample log is worth keeping against how long a report is, where the artefacts live, and what someone can still answer about a release once the oldest of them has expired.

## What each artefact is for A nightly run that nobody watches has to leave behind enough for somebody to answer a question next month. Three files or trees carry different answers, and they are not substitutes for one another. | Artefact | Named by | Holds | Why archive it | |---|---|---|---| | Sample log (JTL) | `-l results.jtl` | One row per sample result | The only source a report can be rebuilt from | | Dashboard | `-o report` | `index.html`, `content/`, `sbadmin2-*/`, `statistics.json` | What a human opens without tooling | | Run log | `-j`, default `jmeter.log` | Engine and error messages | The only record of why a run misbehaved | ## The dashboard is a website, not a page This is the mistake that costs the most, because it is invisible until somebody opens the archive. The HTML exporter does not render one self-contained file. It reads a template directory — `bin/report-template` by default, overridable with the `template_dir` property — and walks the whole tree, processing FreeMarker templates and copying everything else through. The result mirrors the template: an `index.html` at the top, a `content/` directory with the generated pages, CSS and JavaScript, and a vendored `sbadmin2-*` theme directory holding the styling and charting assets. JMeter's own safety check for that folder recognises exactly those three names. Alongside them, the JSON exporter is enabled by default and writes `statistics.json` into the same directory, because `-o` sets the property `jmeter.reportgenerator.outputdir`, which overrides each exporter's own configured output directory. That file is the machine-readable sibling of the summary table, and it is the one a later job can diff without parsing HTML. So: archive the directory. An artefact step that uploads `report/index.html` because the glob looked tidy produces a page that loads and renders nothing. ## Why the JTL still matters when you already have the report The dashboard is a derived view. The JTL is the run. Keeping both is not redundancy for its own sake: - A report can be regenerated from a JTL later, with different report-generator properties, once you know what question you are asking. - The JTL still holds per-sample rows, which the aggregated dashboard has already collapsed. - Which columns the JTL contains was fixed by the save-service properties in force at run time, so the archive freezes not just the data but the decision about what data existed. That is worth knowing before the archive is the only copy. The practical caution is size. A long nightly run can produce a very large sample log; compress it in the archive step and decide its retention separately from the report's, because the two are wanted at different frequencies. ## The run log disappears if you do not take it `jmeter.log` is the artefact people forget until they need it. The shipped `log4j2.xml` declares its file appender with `append="false"`, so every run truncates and rewrites it. Unlike the sample log, which accumulates across reruns, this one keeps only the latest. Two ways to keep it: 1. Archive `jmeter.log` from the workspace as part of the same artefact step. 2. Give each run its own name with `-j`, so the file is distinguishable before it is archived at all. Without it, a failed nightly leaves you a red build and no engine-side explanation. ## Putting it together A workable convention for a job that archives its report: - Write `-l` and `-o` under one per-run directory, so the archive step has a single path to upload and reruns cannot collide. - Upload that directory whole, including the report subtree, the sample log and the run log. - Keep the report as the thing people click and the JTL as the thing people re-process, with retention set accordingly. What this leaf does not decide is what the numbers inside those artefacts should be, or what makes a run's result acceptable — those belong elsewhere. The build step's job is narrower and completely checkable: produce the artefacts, and archive all of each one.

  • The archived report opens as an unstyled page with no charts. What did the artefact step get wrong?
    It uploaded `index.html` alone. The exporter copies a whole template tree, so the styling, the generated pages and the charting assets live in `content/` and a `sbadmin2-*` directory beside the index. Archive the directory named by `-o` in full, and the page renders exactly as it did on the agent.
  • If disk is tight, which of the three artefacts would you shorten retention on first?
    The sample log, but only after deciding you will not need to re-derive anything from it. It is by far the largest and the least often opened, while the report is what people click and `jmeter.log` is small. The trade is that once the JTL is gone you can no longer regenerate a report or look at individual samples.
  • Why does statistics.json land in the -o folder rather than the exporter's configured directory?
    Because `-o` sets the property `jmeter.reportgenerator.outputdir`, and each exporter prefers that globally defined value over its own `output_dir` setting. The HTML and JSON exporters therefore both write into the folder the command line named, which is what makes a single archive path sufficient.

The dashboard is a small website, not a document. Archiving index.html alone is like keeping one page torn out of a printed booklet: the words survive, but every chart, style sheet and script stayed behind in the folder you did not take.

saying these in an interview costs you the question

  • Archives index.html only and calls the report captured
  • Treats the dashboard as a substitute for the sample log
  • Assumes jmeter.log survives the next run
  • Uploads the workspace root instead of a per-run path
  • Gives report and sample log the same retention without thinking