skip to content

Your JMeter JSR223 script calls log.debug and nothing reaches jmeter.log. Why?

level: seniorimportance: should knowfreq 40%

answer

  1. The binding is a standard logging interface
  2. Something upstream decides whether a level passes
  3. Its name is built from two parts
  4. Check the file in bin, not the plan

basics

~20 s

The shipped bin/log4j2.xml sets the root logger to info, so debug events are dropped. The log binding is a real SLF4J Logger named after the element's class plus its tree name; raise that name's level, or use log.info.

solid answer

~30 s

`log` is not a JMeter-specific helper: `populateBindings` calls `LoggerFactory.getLogger(getClass().getName() + "." + getName())`, so the script gets an SLF4J `Logger` whose name is the element's class followed by the element's name in the tree — for example `org.apache.jmeter.extractor.JSR223PostProcessor.capture order id`. Levels are decided by `bin/log4j2.xml`, whose `<Root level="info">` swallows anything below info. Two fixes: add a `<Logger>` entry for that class or its package and set `level="debug"`, or start the run with `-L`, which takes `[category=]level` and prefixes `org.apache.` to a category beginning `jmeter` or `jorphan`. `log.info` from a script needs neither.

code

xml · 10 lines
xml
<!-- bin/log4j2.xml -->
<Loggers>
  <Root level="info">
    <AppenderRef ref="jmeter-log" />
    <AppenderRef ref="gui-log-event" />
  </Root>

  <!-- turn on debug for every JSR223 PostProcessor's script logger -->
  <Logger name="org.apache.jmeter.extractor.JSR223PostProcessor" level="debug" />
</Loggers>

go deeper

for a junior

Recall that log is an SLF4J Logger and that log.info reaches jmeter.log out of the box while log.debug does not, because the shipped configuration starts at info.

for a middle

Explain the logger name JMeter builds from the element class and the element's tree name, and how log4j2's dot-separated hierarchy lets a class or package entry set the level for it.

for a senior

Show the diagnosis path end to end: check bin/log4j2.xml, know that -L takes [category=]level, and decide what a plan may log per sample before a run at scale rather than after it.

for a principal

Own the convention for the fleet: which log level injectors run at, whether log4j2.xml is version-controlled with the plans, and what evidence belongs in the results file rather than in a log.

The `log` binding is one of the few in a JSR223 element that is not a JMeter object at all. It is an SLF4J `Logger`, and everything about whether your line appears is decided by log4j2's configuration, not by JMeter. ## How the logger is named `JSR223TestElement.populateBindings` builds it per invocation: ```java Logger elementLogger = LoggerFactory.getLogger(getClass().getName() + "." + getName()); bindings.put("log", elementLogger); ``` So for a JSR223 PostProcessor named `capture order id`, the logger name is: ``` org.apache.jmeter.extractor.JSR223PostProcessor.capture order id ``` Two consequences worth knowing: - The name is per **element**, not per element type. Two scripts in one plan have two logger names, so you can turn one on and leave the other quiet. - log4j2's hierarchy is dot-separated, so a `<Logger>` entry for `org.apache.jmeter.extractor.JSR223PostProcessor`, or for the package above it, is an ancestor of that name and its level applies. You do not have to spell out the element name (which contains spaces). The pre-processor's class is `org.apache.jmeter.modifiers.JSR223PreProcessor`; the post-processor's is `org.apache.jmeter.extractor.JSR223PostProcessor`. ## Why nothing appeared `bin/log4j2.xml` ships with: ```xml <Root level="info"> <AppenderRef ref="jmeter-log" /> <AppenderRef ref="gui-log-event" /> </Root> ``` No `<Logger>` is configured for any JSR223 class, so the script's logger inherits `info` from the root and `log.debug(...)` is filtered before it reaches an appender. `log.info(...)` and above go to the `jmeter-log` file appender, whose file name comes from the `jmeter.logfile` system property and defaults to `jmeter.log`, and — in GUI mode — to the log panel through the `GuiLogEvent` appender. ## Turning it on - **Permanently, for that element family:** add `<Logger name="org.apache.jmeter.extractor.JSR223PostProcessor" level="debug" />` inside `<Loggers>` in `bin/log4j2.xml`. - **For one run:** pass `-L`, documented as `[category=]level`. `-L jmeter.extractor=DEBUG` becomes `org.apache.jmeter.extractor` because JMeter prefixes `org.apache.` to categories starting `jmeter` or `jorphan`; `-L DEBUG` with no category sets the root level instead, which turns on everything. - **Neither:** log at info from the script, or write the value into a variable and read it with a Debug Sampler. ## Judgment at load Log volume is a property of the plan you control, and a script that logs a line per sample writes one line per sample per thread. A few things to settle before a big run: 1. Use the placeholder form, `log.info("order {} on thread {}", id, ctx.getThreadNum())`, so the message is only assembled when the level is enabled. 2. Guard expensive constructions with `log.isDebugEnabled()`. 3. Leave debug lines in the script but off in the configuration, rather than deleting them; the per-element logger name is what makes that practical. 4. Remember the shipped appender is a plain `<File>` with `append="false"`, so each start truncates `jmeter.log` — keep the file from a failed run before you re-run. ## What `log` is not It is not a channel to the results file. Nothing a script logs reaches the JTL, the HTML dashboard or a listener; those are fed by `SampleResult`. If a value must survive the run in an analysable form, it belongs in the sample result or in a variable a listener records, not in a log line.

  • How would you raise the level for one JMeter JSR223 element without editing bin/log4j2.xml?
    Start the run with `-L`, which takes `[category=]level`. `-L jmeter.extractor=DEBUG` resolves to `org.apache.jmeter.extractor` because JMeter prefixes `org.apache.` to categories beginning `jmeter` or `jorphan`. It is coarser than a per-element entry, but it needs no file edit and lasts only for that run.
  • Can a JMeter script's log lines be used as the run's evidence instead of the results file?
    No. Nothing written through the `log` binding reaches the JTL, a listener or the HTML dashboard — those are built from `SampleResult`. Log lines are for diagnosis. A value that must be analysed afterwards belongs in the sample result or in a variable something records.

saying these in an interview costs you the question

  • Thinks the log binding writes into the results file
  • Cannot say where the log level is configured
  • Assumes every element shares one logger name
  • Concatenates strings instead of using placeholders
  • Forgets the shipped appender truncates jmeter.log on start