| //// |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| //// |
| = Flow Tracing |
| |
| Flow tracing in Log4j is an advanced logging technique designed to enhance |
| the visibility of application processes. With this technique, developers can track |
| the flow of data through their application by using special methods that log entry |
| and exit points within the code. |
| |
| These methods are: |
| |
| * `entry()` or `traceEntry()` |
| * `exit()` or `traceExit()` |
| * `throwing()` |
| * `catching()` |
| |
| With these methods, we can investigate environments where traditional debugging is not possible, |
| such as in production or during live application monitoring. |
| Furthermore, new developers can be educated on the application's behavior by examining the logs. |
| |
| Flow tracing offers a structured approach to all this. |
| |
| == Flow Tracing Methods |
| |
| The methods used most often are `entry()` or `traceEntry()` and `exit()` or `traceExit()`. |
| As the name suggests, the "entry" methods are used at the beginning of a method, |
| while the "exit" methods are used at the end of a method. |
| |
| [source, java] |
| ---- |
| public void someMethod() { |
| logger.entry(); <1> |
| // method body |
| logger.exit(); <2> |
| } |
| ---- |
| <1> The `entry()` method is called at the beginning of the method. |
| <2> The `exit()` method is called at the end of the method. |
| |
| Both `entry()` and `exit()` methods can be called with or without parameters. |
| In the case of `entry()` it makes sense to pass the method parameters as arguments. |
| |
| [source, java] |
| ---- |
| public void someMethod(String param) { |
| logger.entry(param); <1> |
| // method body |
| logger.exit(); <2> |
| } |
| ---- |
| <1> The `entry()` method is called at the beginning of the method. |
| |
| The `traceEntry()` also supports messages. |
| |
| [source, java] |
| ---- |
| public void someMethod(String[] text) { |
| logger.traceEntry(new JsonMessage(text)); <1> |
| // method body |
| } |
| ---- |
| <1> Using the `JsonMessage` class to log the `text` parameter. |
| |
| Very similar, it is possible to use `exit()` with methods that return a value. |
| |
| [source, java] |
| ---- |
| public String someMethod() { |
| String result = "Hello"; |
| // method body |
| return logger.exit(result); <1> |
| } |
| ---- |
| <1> The `exit()` method can also return a value. |
| |
| To work with exceptions, the `catching()` and `throwing()` methods are used. |
| |
| The following code shows, how to use the `catching()` method. It will be called |
| inside the `catch` block of a try-catch statement. |
| |
| The `catching()` method can be used by an application when it catches an |
| Exception that it is not going to rethrow, either explicitly or attached |
| to another Exception. The logging event generated will have a level of `ERROR`. |
| |
| [source, java] |
| ---- |
| public void someMethod() { |
| try { |
| // Lets assume an exception is thrown here |
| String msg = messages[messages.length]; |
| } catch (Exception ex) { |
| logger.catching(ex); <1> |
| } |
| } |
| ---- |
| <1> The `catching()` method is used to log exceptions that are caught and not rethrown. |
| |
| The `throwing()` method is used to log exceptions that are thrown and not caught. |
| The code shows how to use the `throwing()` method- like `catching()` it will be called |
| inside the `catch` block of a try-catch statement. |
| |
| The `throwing()` method can be used by an application when it is throwing |
| an exception that is unlikely to be handled, such as a RuntimeException. |
| This will ensure that proper diagnostics are available if needed. The |
| logging event generated will have a level of `ERROR`. |
| |
| [source, java] |
| ---- |
| public void someMethod() { |
| try { |
| // Lets assume an exception is thrown here |
| String msg = messages[messages.length]; |
| } catch (Exception ex) { |
| logger.throwing(ex); <1> |
| } |
| } |
| ---- |
| <1> The `throwing()` method is used to log exceptions that are thrown and not caught. |
| |
| == Differences in flow tracing methods |
| |
| Flow tracing methods have specific markers assigned and logs with a level of `TRACE`. |
| It's also noteworthy that all messages will begin with the word "event". |
| |
| The table below shows the methods and their special features. |
| |
| [cols="3,3,3", options="header"] |
| |=== |
| | Method Name | Marker Name | Special Features |
| |
| | `entry()` |
| | `ENTER`, `FLOW` |
| | Accepts 0 to 4 parameters |
| |
| | `traceEntry()` |
| | `ENTER`, `FLOW` |
| | Can take a format string and a variable list of parameters. |
| |
| | `exit()` |
| | `EXIT`, `FLOW` |
| | Can be called with or without parameters. |
| |
| | `traceExit()` |
| | `EXIT`, `FLOW` |
| | Handles return values differently based on the method signature. |
| |
| | `throwing()` |
| | `THROWING`, `EXCEPTION` |
| | Typically used when an application throws an exception that is unlikely to be handled, such as a RuntimeException. |
| |
| | `catching()` |
| | `CATCHING`, `EXCEPTION` |
| | Used when catching exceptions that are not rethrown; logs with ERROR level. |
| |
| |=== |
| |
| == Flow Tracing Example Configuration |
| |
| The following example demonstrates how to configure Log4j to use flow tracing. |
| While it is recommended to use the `JsonTemplateLayout` in production, we are using the |
| `PatternLayout` in this example for simplicity. |
| |
| The configuration below will cause all output to be routed to |
| target/test.log. The pattern for the FileAppender includes the class |
| name, line number and method name. Including these in the pattern is |
| critical for the log to be of value. |
| |
| The following example demonstrates how you could use flow tracing. |
| The Configuration element is set with a status of "error," which means Log4j |
| will only report issues that are of error severity or higher. |
| Within the Appenders section, two appenders are defined: Console and File. |
| |
| The Console appender is configured to output logs to `SYSTEM_OUT`, typically the console. |
| It includes a `ThresholdFilter` set to only accept messages at the `ERROR` level or above. |
| This filters out less severe messages. |
| The output format is specified by a `PatternLayout`, designed to include detailed |
| trace information such as time, log level, class name, line number, and method name. |
| Please note, that we are recommending `JsonTemplateLayout` over `PatternLayout` in production. |
| |
| Similarly, the File appender directs logs to a file named `target/test.log`. |
| The appenders configuration will create a new file for every application run. |
| |
| Finally, in the Loggers section, the Root logger is set to a `TRACE` level which is necessary |
| to see flow tracing in action. The Root logger references the File appender, directing |
| its output to the configured file. |
| |
| [source,xml] |
| ---- |
| <?xml version="1.0" encoding="UTF-8"?> |
| <Configuration status="error"> |
| <Appenders> |
| <Console name="Console" target="SYSTEM_OUT"> |
| <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/> |
| <!-- Flow tracing is most useful with a pattern that shows location. |
| Below pattern outputs class, line number and method name. --> |
| <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/> |
| </Console> |
| <File name="log" fileName="target/test.log" append="false"> |
| <PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %class{36} %L %M - %msg%xEx%n"/> |
| </File> |
| </Appenders> |
| <Loggers> |
| <Root level="trace"> |
| <AppenderRef ref="log"/> |
| </Root> |
| </Loggers> |
| </Configuration> |
| ---- |
| |
| By changing the level of the Root logger to `DEBUG`, you can reduce the amount of output. |