Chapter 4. Debugging Eclipse Vert.x based application
Chapter 4. Debugging Eclipse Vert.x based application This sections contains information about debugging your Eclipse Vert.x-based application both in local and remote deployments. 4.1. Remote debugging To remotely debug an application, you must first configure it to start in a debugging mode, and then attach a debugger to it. 4.1.1. Starting your application locally in debugging mode One of the ways of debugging a Maven-based project is manually launching the application while specifying a debugging port, and subsequently connecting a remote debugger to that port. This method is applicable at least to the following deployments of the application: When launching the application manually using the mvn vertx:debug goal. This starts the application with debugging enabled. Prerequisites A Maven-based application Procedure In a console, navigate to the directory with your application. Launch your application and specify the debug port using the -Ddebug.port argument: USD mvn vertx:debug -Ddebug.port=USDPORT_NUMBER Here, USDPORT_NUMBER is an unused port number of your choice. Remember this number for the remote debugger configuration. Use the -Ddebug.suspend=true argument to make the application wait until a debugger is attached to start. 4.1.2. Starting your application on OpenShift in debugging mode To debug your Eclipse Vert.x-based application on OpenShift remotely, you must set the JAVA_DEBUG environment variable inside the container to true and configure port forwarding so that you can connect to your application from a remote debugger. Prerequisites Your application running on OpenShift. The oc binary installed. The ability to execute the oc port-forward command in your target OpenShift environment. Procedure Using the oc command, list the available deployment configurations: USD oc get dc Set the JAVA_DEBUG environment variable in the deployment configuration of your application to true , which configures the JVM to open the port number 5005 for debugging. For example: USD oc set env dc/MY_APP_NAME JAVA_DEBUG=true Redeploy the application if it is not set to redeploy automatically on configuration change. For example: USD oc rollout latest dc/MY_APP_NAME Configure port forwarding from your local machine to the application pod: List the currently running pods and find one containing your application: USD oc get pod NAME READY STATUS RESTARTS AGE MY_APP_NAME-3-1xrsp 0/1 Running 0 6s ... Configure port forwarding: USD oc port-forward MY_APP_NAME-3-1xrsp USDLOCAL_PORT_NUMBER:5005 Here, USDLOCAL_PORT_NUMBER is an unused port number of your choice on your local machine. Remember this number for the remote debugger configuration. When you are done debugging, unset the JAVA_DEBUG environment variable in your application pod. For example: USD oc set env dc/MY_APP_NAME JAVA_DEBUG- Additional resources You can also set the JAVA_DEBUG_PORT environment variable if you want to change the debug port from the default, which is 5005 . 4.1.3. Attaching a remote debugger to the application When your application is configured for debugging, attach a remote debugger of your choice to it. In this guide, Red Hat CodeReady Studio is covered, but the procedure is similar when using other programs. Prerequisites The application running either locally or on OpenShift, and configured for debugging. The port number that your application is listening on for debugging. Red Hat CodeReady Studio installed on your machine. You can download it from the Red Hat CodeReady Studio download page . Procedure Start Red Hat CodeReady Studio. Create a new debug configuration for your application: Click Run->Debug Configurations . In the list of configurations, double-click Remote Java application. This creates a new remote debugging configuration. Enter a suitable name for the configuration in the Name field. Enter the path to the directory with your application into the Project field. You can use the Browse... button for convenience. Set the Connection Type field to Standard (Socket Attach) if it is not already. Set the Port field to the port number that your application is listening on for debugging. Click Apply. Start debugging by clicking the Debug button in the Debug Configurations window. To quickly launch your debug configuration after the first time, click Run->Debug History and select the configuration from the list. Additional resources Debug an OpenShift Java Application with JBoss Developer Studio on Red Hat Knowledgebase. Red Hat CodeReady Studio was previously called JBoss Developer Studio. A Debugging Java Applications On OpenShift and Kubernetes article on OpenShift Blog. 4.2. Debug logging Eclipse Vert.x provides a built-in logging API. The default logging implementation for Eclipse Vert.x uses the java.util.logging library that is provided with the Java JDK . Alternatively, Eclipse Vert.x allows you to use a different logging framework, for example, Log4J (Eclipse Vert.x supports Log4J v1 and v2) or SLF4J . 4.2.1. Configuring logging for your Eclipse Vert.x application using java.util.logging To configure debug logging for your Eclipse Vert.x application using java.util.logging : Set the java.util.logging.config.file system property in the application.properties file. The value of this variable must correspond to the name of your java.util.logging configuration file . This ensures that LogManager initializes java.util.logging at application startup. Alternatively, add a java.util.logging configuration file with the vertx-default-jul-logging.properties name to the classpath of your Maven project. Eclipse Vert.x will use that file to configure java.util.logging on application startup. Eclipse Vert.x allows you to specify a custom logging backend using the LogDelegateFactory that provides pre-built implementations for the Log4J , Log4J2 and SLF4J libraries. Unlike java.util.logging , which is included with Java by default, the other backends require that you specify their respective libraries as dependencies for your application. 4.2.2. Adding log output to your Eclipse Vert.x application. To add logging to your application, create a io.vertx.core.logging.Logger : Logger logger = LoggerFactory.getLogger(className); logger.info("something happened"); logger.error("oops!", exception); logger.debug("debug message"); logger.warn("warning"); Caution Logging backends use different formats to represent replaceable tokens in parameterized messages. If you rely on parameterized logging methods, you will not be able to switch logging backends without changing your code. 4.2.3. Specifying a custom logging framework for your application If you do not want Eclipse Vert.x to use java.util.logging , configure io.vertx.core.logging.Logger to use a different logging framework, for example, Log4J or SLF4J : Set the value of the vertx.logger-delegate-factory-class-name system property to the name of the class that implements the LogDelegateFactory interface. Eclipse Vert.x provides the pre-built implementations for the following libraries with their corresponding pre-defined classnames listed below: Library Class name Log4J v1 io.vertx.core.logging.Log4jLogDelegateFactory Log4J v2 io.vertx.core.logging.Log4j2LogDelegateFactory SLF4J io.vertx.core.logging.SLF4JLogDelegateFactory When implementing logging using a custom library, ensure that the relevant Log4J or SLF4J jars are included among the dependencies for your application. Caution The Log4J v1 delegate provided with Eclipse Vert.x does not support parameterized messages. The delegates for Log4J v2 and SLF4J both use the {} syntax. The java.util.logging delegate relies on java.text.MessageFormat that uses the {n} syntax. 4.2.4. Configuring Netty logging for your Eclipse Vert.x application. Netty is a library used by VertX to manage asynchronous network communication in applications. Netty: Allows quick and easy development of network applications, such as protocol servers and clients. Simplifies and streamlines network programming, such as TCP and UDP socket server development. Provides a unified API for managing blocking and non-blocking connections. Netty does not rely on an external logging configuration using system properties. Instead, it implements a logging configuration based on logging libraries visible to Netty classes in your project. Netty tries to use the libraries in the following order: SLF4J Log4J java.util.logging as a fallback option You can set io.netty.util.internal.logging.InternalLoggerFactory directly to a particular logger by adding the following code at the beginning of the main method of your application: // Force logging to Log4j InternalLoggerFactory.setDefaultFactory(Log4JLoggerFactory.INSTANCE); 4.2.5. Accessing debug logs on OpenShift Start your application and interact with it to see the debugging statements in OpenShift. Prerequisites The oc CLI client installed and authenticated. A Maven-based application with debug logging enabled. Procedure Deploy your application to OpenShift: USD mvn clean oc:deploy -Popenshift View the logs: Get the name of the pod with your application: USD oc get pods Start watching the log output: USD oc logs -f pod/MY_APP_NAME-2-aaaaa Keep the terminal window displaying the log output open so that you can watch the log output. Interact with your application: For example, the following command is based on an example REST API level 0 application where debug logging is set to log the message variable in the /api/greeting method: Get the route of your application: USD oc get routes Make an HTTP request on the /api/greeting endpoint of your application: USD curl USDAPPLICATION_ROUTE/api/greeting?name=Sarah Return to the window with your pod logs and inspect debug logging messages in the logs. To disable debug logging, update your logging configuration file, for example src/main/resources/vertx-default-jul-logging.properties , remove the logging configuration for your class and redeploy your application.
mvn vertx:debug -Ddebug.port=USDPORT_NUMBER oc get dc oc set env dc/MY_APP_NAME JAVA_DEBUG=true oc rollout latest dc/MY_APP_NAME oc get pod NAME READY STATUS RESTARTS AGE MY_APP_NAME-3-1xrsp 0/1 Running 0 6s oc port-forward MY_APP_NAME-3-1xrsp USDLOCAL_PORT_NUMBER:5005 oc set env dc/MY_APP_NAME JAVA_DEBUG- Logger logger = LoggerFactory.getLogger(className); logger.info("something happened"); logger.error("oops!", exception); logger.debug("debug message"); logger.warn("warning"); // Force logging to Log4j InternalLoggerFactory.setDefaultFactory(Log4JLoggerFactory.INSTANCE); mvn clean oc:deploy -Popenshift oc get pods oc logs -f pod/MY_APP_NAME-2-aaaaa oc get routes curl USDAPPLICATION_ROUTE/api/greeting?name=Sarah Feb 11, 2017 10:23:42 AM io.openshift.MY_APP_NAME INFO: Greeting: Hello, Sarah