Debugging Pulsar source code in IDE
Debugging the Pulsar with its source code can be essential for identifying and resolving issues during development. This page provides step-by-step instructions on debugging Pulsar in standalone mode and debugging the source version of Apache Pulsar.
Debugging Pulsar in Standalone Mode
Download and Extract Pulsar Binary Distribution
Download the binary distribution of the desired Pulsar release and extract it to a directory of your choice.
Run Pulsar in Standalone Mode with Debugger Options
Navigate to the Pulsar directory and run the following command:
OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005" ./bin/pulsar standalone -nss -nfw
suspend=n
allows the process to start without waiting for the debugger to connect immediately. You can change suspend=n
to suspend=y
if you want the process to wait for the debugger to connect.
In your IDE, follow the instructions at Setting up an IDE to configure your IDE for Pulsar development.
Configure IntelliJ IDEA for Remote Debugging
First, Open Your Pulsar Project in IntelliJ IDEA:
- Open IntelliJ IDEA.
- Go to
File > Open
and navigate to your Pulsar project.
Then, create a Remote Debugger Configuration:
- Open the
Run/Debug Configurations
dialog by clicking on the dropdown near the top-right corner (next to theRun/Debug
button) and selectingEdit Configurations
. - Click the
+
button to add a new configuration and chooseRemote
from the list. - Provide a name for your configuration (e.g., "Pulsar Remote Debugger").
- Set
Debugger mode
toAttach to remote JVM
. - Set
Host
to localhost or the IP address of the machine running Pulsar. - Set
Port
to the same port number used in your Pulsar startup command (e.g., 5005). - Click
Ok
to save the configuration.
To reset the persistent state, you can remove data under the data
folder before starting, with: rm -rf data
.
Debugging the source version of Pulsar
Clone and compile Pulsar from source code and run Pulsar in standalone mode with debugger options:
git clone https://github.com/apache/pulsar
cd pulsar
mvn -Pcore-modules,-main -T 1C install -DskipTests -Dspotbugs.skip=true
OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005" ./bin/pulsar standalone -nss -nfw
Debugging pulsar-shell and pulsar-client
# For Pulsar-Shell
OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005" ./bin/pulsar-shell
# For Pulsar-Client
# Consumer
OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005" ./bin/pulsar-client consume -s sub apache/pulsar/test-topic -n 0
# Producer
OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005" ./bin/pulsar-client produce apache/pulsar/test-topic -m "---------hello apache pulsar-------" -n 10
Ensure that the debugger is configured in your IDE to connect to the specified port.
By following these steps, you can effectively debug both the standalone mode and the source version of Apache Pulsar, including pulsar-shell and pulsar-client processes.
Enabling debug logging for specific classes when running unit tests in IDE or locally
When working on Pulsar unit tests, you sometimes want to enable debug logging for a specific class, a set of classes, or a certain package to observe what the code is doing while you're running it. Stepping through with a debugger isn't a feasible approach for different race conditions and when timings and timeouts are involved. In those cases, you could add debug log statements to the code if they don't already exist. This helps understand the behavior of a failing test case.
For tests in the pulsar-broker module, you need to edit the pulsar-broker/src/test/resources/log4j2.xml
file to enable logging. Adding a Logger
element in Loggers
can be used to enable debug logging for a complete package tree or specific classes.
<Logger name="<<package or classname>>" level="DEBUG" additivity="false">
<AppenderRef ref="CONSOLE"/>
</Logger>
Here's an example:
<Configuration xmlns="http://logging.apache.org/log4j/2.0/config"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://logging.apache.org/log4j/2.0/config https://logging.apache.org/log4j/2.0/log4j-core.xsd">
<Appenders>
<!-- setting follow="true" is required for using ConsoleCaptor to validate log messages -->
<Console name="CONSOLE" target="SYSTEM_OUT" follow="true">
<PatternLayout pattern="%d{ISO8601} - %-5p - [%t:%c{1}] - %m%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="CONSOLE"/>
</Root>
<Logger name="org.apache.pulsar.broker.service.persistent.PersistentStickyKeyDispatcherMultipleConsumers" level="DEBUG" additivity="false">
<AppenderRef ref="CONSOLE"/>
</Logger>
<!-- loggers for debugging Key_Shared / PIP-379 -->
<Logger name="org.apache.pulsar.broker.service.persistent.PersistentStickyKeyDispatcherMultipleConsumers" level="DEBUG" additivity="false">
<AppenderRef ref="CONSOLE"/>
</Logger>
<Logger name="org.apache.pulsar.broker.service.DrainingHashesTracker" level="DEBUG" additivity="false">
<AppenderRef ref="CONSOLE"/>
</Logger>
<Logger name="org.apache.pulsar.broker.service.persistent.RescheduleReadHandler" level="DEBUG" additivity="false">
<AppenderRef ref="CONSOLE"/>
</Logger>
</Loggers>
</Configuration>
You can also set debugging at a package level to debug and exclude classes that are causing verbose logging. In those cases, you'd set the log level to WARN
for the classes that are too verbose for your debugging case.
<Logger name="org.apache.pulsar.client.impl.ClientCnx" level="WARN" additivity="false">
<AppenderRef ref="CONSOLE"/>
</Logger>
The same approach can be used to modify Pulsar standalone's logging configuration available at conf/log4j2.yaml
when you are debugging Pulsar standalone instead of debugging a Pulsar unit test failure. The main difference is that the syntax is in YAML. The default config file contains examples for over logger-specific configuration.