Skip to content

Latest commit

 

History

History
708 lines (591 loc) · 20.8 KB

README.asciidoc

File metadata and controls

708 lines (591 loc) · 20.8 KB

DebugTrace-java

DebugTrace-java is a library that outputs trace logs when debugging Java programs.
By embedding DebugTrace.enter() and DebugTrace.leave() at the start and end of methods, you can output the execution status of the Java program under development to the log.

DebugTrace-java version Java version to support

DebugTrace-java 4.x.x

Java 17 and later

DebugTrace-java 3.x.x

Java 8 and later

1. Features

  • Automatically outputs invoker’s class name, method name, source file and line number.

  • Automatically indents the log with nesting methods and objects.

  • Automatically output logs when changing threads.

  • Uses reflection to output the contents of classes that do not implement the toString method.

  • You can customize the output content in DebugTrace.properties.

  • There are no dependent libraries at run time. (Required if you use the following logging library)

  • You can use the following logging library.

2. How to use

Insert the following for the debuggee and related methods.

  • DebugTrace.enter();

  • DebugTrace.leave();

  • DebugTrace.print("value", value);

(1) If the method does not throw an exception and does not return in the middle.
public void foo() {
    DebugTrace.enter(); // TODO: Remove after debugging
    ...
    DebugTrace.print("value", value); // TODO: Remove after debugging
    ...
    DebugTrace.leave(); // TODO: Remove after debugging
}
(2) If the method does not throw an exception, but there are returns in the middle.
public void foo() {
    try {DebugTrace.enter(); // TODO: Remove after debugging
    ...
    DebugTrace.print("value", value); // TODO: Remove after debugging
    ...
    if (...)
        return;
    ...
    } finally {DebugTrace.leave();} // TODO: Remove after debugging
}
(3) If the method throws an exception.
public void foo() throws Exception {
    try {DebugTrace.enter(); // TODO: Remove after debugging
    ...
    DebugTrace.print("value", value); // TODO: Remove after debugging
    ...
    if (...)
        throw new Exception();
    ...
    } catch (Exception e) {DebugTrace.print("e", e); throw e; // TODO: Remove after debugging
    } finally {DebugTrace.leave();} // TODO: Remove after debugging
}

The following is an example of Java source used DebugTrace-java methods and the log of when it has been executed.

Example1.java
package example;

import java.util.HashMap;
import java.util.Map;

import org.debugtrace.DebugTrace;

public class Example1 {
    private static final Map<Long, Long> fibonacciMap = new HashMap<>();
    static {
        fibonacciMap.put(0L, 0L);
        fibonacciMap.put(1L, 1L);
    }

    public static void main(String[] args) {
        DebugTrace.enter(); // TODO: Remove after debugging
        try {
            if (args.length <= 0)
                throw new IllegalArgumentException("args.length = " + args.length);
            long n = Long.parseLong(args[0]);
            long fibonacci = fibonacci(n);
            System.out.println("fibonacci(" + n + ") = " + fibonacci);
        } catch (Exception e) {
            DebugTrace.print("e", e); // TODO: Remove after debugging
        }
        DebugTrace.leave(); // TODO: Remove after debugging
    }

    public static long fibonacci(long n) {
        DebugTrace.enter(); // TODO: Remove after debugging
        if (n < 0)
            throw new IllegalArgumentException("n (" + n + ") is negative.");
        long fibonacci = 0;
        if (fibonacciMap.containsKey(n)) {
            fibonacci = fibonacciMap.get(n);
            DebugTrace.print("mapped fibonacci(" + n + ")", fibonacci); // TODO: Remove after debugging
        } else {
            fibonacci = fibonacci(n - 2) + fibonacci(n - 1);
            DebugTrace.print("fibonacci(" + n + ")", fibonacci); // TODO: Remove after debugging
            if (fibonacci < 0)
                throw new RuntimeException("Overflow occurred in fibonacci(" + n + ") calculation.");
            fibonacciMap.put(n, fibonacci);
        }
        DebugTrace.leave(); // TODO: Remove after debugging
        return fibonacci;
    }
}
debugtrace.log
2023-04-16 08:03:10.363+09:00 DebugTrace 4.0.0 on Amazon.com Inc. OpenJDK Runtime Environment 17.0.6+10-LTS
2023-04-16 08:03:10.363+09:00   property name: DebugTrace.properties
2023-04-16 08:03:10.363+09:00   logger: org.debugtrace.logger.Std$Err
2023-04-16 08:03:10.385+09:00
2023-04-16 08:03:10.388+09:00 ______________________________ main ______________________________
2023-04-16 08:03:10.388+09:00
2023-04-16 08:03:10.388+09:00 Enter example.Example1.main (Example1.java:18) <- (:0)
2023-04-16 08:03:10.389+09:00 | Enter example.Example1.fibonacci (Example1.java:32) <- (Example1.java:23)
2023-04-16 08:03:10.389+09:00 | | Enter example.Example1.fibonacci (Example1.java:32) <- (Example1.java:40)
2023-04-16 08:03:10.432+09:00 | | | mapped fibonacci(1) = (long)1 (Example1.java:38)
2023-04-16 08:03:10.434+09:00 | | Leave example.Example1.fibonacci (Example1.java:46) duration: 00:00:00.044
2023-04-16 08:03:10.434+09:00 | |
2023-04-16 08:03:10.434+09:00 | | Enter example.Example1.fibonacci (Example1.java:32) <- (Example1.java:40)
2023-04-16 08:03:10.434+09:00 | | | Enter example.Example1.fibonacci (Example1.java:32) <- (Example1.java:40)
2023-04-16 08:03:10.434+09:00 | | | | mapped fibonacci(0) = (long)0 (Example1.java:38)
2023-04-16 08:03:10.436+09:00 | | | Leave example.Example1.fibonacci (Example1.java:46) duration: 00:00:00.000
2023-04-16 08:03:10.436+09:00 | | |
2023-04-16 08:03:10.436+09:00 | | | Enter example.Example1.fibonacci (Example1.java:32) <- (Example1.java:40)
2023-04-16 08:03:10.436+09:00 | | | | mapped fibonacci(1) = (long)1 (Example1.java:38)
2023-04-16 08:03:10.436+09:00 | | | Leave example.Example1.fibonacci (Example1.java:46) duration: 00:00:00.000
2023-04-16 08:03:10.436+09:00 | | | fibonacci(2) = (long)1 (Example1.java:41)
2023-04-16 08:03:10.436+09:00 | | Leave example.Example1.fibonacci (Example1.java:46) duration: 00:00:00.001
2023-04-16 08:03:10.436+09:00 | | fibonacci(3) = (long)2 (Example1.java:41)
2023-04-16 08:03:10.437+09:00 | Leave example.Example1.fibonacci (Example1.java:46) duration: 00:00:00.047
fibonacci(3) = 2
2023-04-16 08:03:10.437+09:00 Leave example.Example1.main (Example1.java:28) duration: 00:00:00.048

3. Method List

This library has the following methods. These are all static methods of org.debugtrace.DebugTrace class.

Table 1. Method List
Method Name Arguments Return Value Description

enter

None

None

Outputs method start to log.

leave

None

None

Outputs method end to log.

print

message: a message

the message

Outputs the message to log.

print

messageSupplier: a supplier of message

tht message getted from the messageSupplier

Gets a message from the supplier and output it to log.

print

name: the value name
value: the value

the value

Outputs to the log in the form of
"Name = Value"
value type is one of the following.
boolean, char,
byte, short, int, long,
float, double, T

print

name: the value name
value: the value
logOptions: LogOptions
The following fields can be specified in logOptions.
minimumOutputSize,
minimumOutputLength,
collectionLimit,
byteArrayLimit,
stringLimit,
reflectionNestLimit
Or the following can be specified.
LogOptions.outputSize
LogOptions.outputLength

the value

Same as above.

print

name: the value name
valueSupplier: the supplier of the value

the value getted from the valueSupplier

Gets a value from the valueSupplier and outputs to the log in the form of
<value name> = <value>
valueSupplier type is one of the following.
BooleanSupplier,
IntSupplier, LongSupplier
Supplier<T>

print

name: the value name
valueSupplier: the supplier of the value
logOptions: LogOptions
See above for details

the value getted from the valueSupplier

Same as above.

printStack

maxCount: maximum number of stack trace elements to output

None

Outputs a list of StackTraceElements to the log.

4. Properties of DebugTrace.properties file

DebugTrace read DebugTrace.properties file in the classpath on startup. You can specify following properties in the DebugTrace.properties file.

Table 2. Property List
Property Name Description Default Value (Value Examples)

logger

Logger used by DebugTrace

Specifiable Values:
Std$Out : Outputs to stdout
Std$Err : Outputs to stderr
Jdk : Outputs using the JDK logger
Log4j : Outputs using the Log4j 1 logger
Log4j2 : Outputs using the Log4j 2 logger
SLF4J : Outputs using the SLF4J logger
File: <log file path> : Outputs to the file
File: +<log file path> : Appends to the file

Std$Err

enterFormat

The format string of logging when entering methods

Parameters:
%1: The class name
%2: The method name
%3: The file name
%4: The line number
%6: The file name of the caller
%7: The line number of the caller

Enter %1$s.%2$s (%3$s:%4$d) ← (%6$s:%7$d)

leaveFormat

The format string of logging when leaving methods

Parameters:
%1: The class name
%2: The method name
%3: The file name
%4: The line number
%5: The duration since invoking the corresponding enter method

Leave %1$s.%2$s (%3$s:%4$d) duration: %5$tT.%5$tL

threadBoundaryFormat

The format string of logging at threads boundary

Parameter:
%1: The thread name

____________________________ %1$s ______________________________

classBoundaryFormat

The format string of logging at classes boundary

Parameter:
%1: The class name

____ %1$s ____

indentString

The indentation string for code

|\\s`

\\s will be change to a space character

dataIndentString

The indentation string for data

\\s\\s

\\s will be change to a space character

limitString

The string to represent that it has exceeded the limit

...

nonOutputString

The string to be output instead of not outputting value

***

cyclicReferenceString

The string to represent that the cyclic reference occurs

\\s*** cyclic reference ***\\s

\\s will be change to a space character

varNameValueSeparator

The separator string between the variable name and value

\\s=\\s

\\s will be change to a space character

keyValueSeparator

The separator string between the key and value of Map object

:\\s

\\s will be change to a space character

printSuffixFormat

The format string of print method suffix
Example:

Parameters:
%1: The class name
%2: The method name
%3: The file name
%4: The line number

\\s(%3$s:%4$d)

\\s will be change to a space character

sizeFormat

The format string of the size of collection and map

Parameters:
%1: The size

\\s(%3$s:%4$d)

\\s will be change to a space character

minimumOutputSize

The minimum value to output the number of elements of array, collection and map

Integer.MAX_VALUE (Same as no output)

lengthFormat

The format string of the length of string

Parameters:
%1: The string length

length:%1d

minimumOutputLength

The minimum value to output the length of string

Integer.MAX_VALUE (Same as no output)

utilDateFormat

The format string of java.util.Date

yyyy-MM-dd HH:mm:ss.SSSxxx

sqlDateFormat

The format string of java.sql.Date

yyyy-MM-ddxxx

timeFormat

The format string of java.sql.Time

HH:mm:ss.SSSxxx

timestampFormat

The format string of java.sql.Timestamp

yyyy-MM-dd HH:mm:ss.SSSSSSSSSxxx

localDateFormat

The format string of java.time.LocalDate

yyyy-MM-dd

localTimeFormat

The format string of java.time.LocalTime

HH:mm:ss.SSSSSSSSS

offsetTimeFormat

The format string of java.time.OffsetTime

HH:mm:ss.SSSSSSSSSxxx

localDateTimeFormat

The format string of java.time.LocalDateTime

yyyy-MM-dd HH:mm:ss.SSSSSSSSS

offsetDateTimeFormat

The format string of java.time.OffsetDateTime

yyyy-MM-dd HH:mm:ss.SSSSSSSSSxxx

zonedDateTimeFormat

The format string of java.time.ZonedDateTime

yyyy-MM-dd HH:mm:ss.SSSSSSSSSxxx VV

instantFormat

The format string of java.time.Instant

yyyy-MM-dd HH:mm:ss.SSSSSSSSSX

logDateTimeFormat

The format string of the date and time of the log when the logger is Std$Out or Std$Err

yyyy-MM-dd HH:mm:ss.SSSxxx

maximumDataOutputWidth

The maximum output width of data

70

collectionLimit

The limit value of elements for collection and map to output

128

byteArrayLimit

The limit value of elements for byte array (byte[]) to output

256

stringLimit

The limit value of characters for string to output

256

reflectionNestLimit

The limit value for reflection nesting

4

nonOutputProperties

Properties not to be output

Format of a value:
<Full class name>#<Property name>

Nome

Example (1 value):
org.lightsleep.helper.EntityInfo#columnInfos

Example (multi values):
org.lightsleep.helper.EntityInfo#columnInfos,\
org.lightsleep.helper.EntityInfo#keyColumnInfos,\
org.lightsleep.helper.ColumnInfo#entityInfo

defaultPackage

The default package of your java source

Nome

Example:
org.debugtrace.DebugTraceExample

defaultPackageString

The string replacing the default package part

...

reflectionClasses

Classe names that output content by reflection even if toString method is implemented

Nome

Example (1 value):
org.debugtrce.example.Point

Example (multi values):
org.debugtrace.example.Point,\
org.debugtrace.example.Rectangle

Example (package):
org.debugtrce.example.

mapNameMap

The map for obtaining map name corresponding to variable name

Format of a value:
<Variable Name>: <Map Name>

Nome

Example:
appleBrand: AppleBrand

<Constant Map Name>

The map of numbers (as key) and constant names (as value) corresponding to the numbers

Format of a value:
<Number>: <Constant Name>

Predefined constant name maps:
Calendar: Calendar.ERA etc.
CalendarWeek: Calendar.SUNDAY etc.
CalendarMonth: Calendar.JANUARY etc.
CalendarAmPm: Calendar.AM etc.
SqlTypes: java.sql.Types.BIT etc.

Example:
AppleBrand = \
   0: Apple.NO_BRAND,\
   1: Apple.AKANE,\
   2: Apple.AKIYO,\
   3: Apple.AZUSA,\
   4: Apple.YUKARI

Specify the date and time format in the format of the argument of the DateTimeFormatter.ofPattern method.

4.1. nonOutputProperties, nonOutputString

DebugTrace use reflection to output object contents if the toString method is not implemented. If there are other object references, the contents of objects are also output. However, if there is circular reference, it will automatically detect and suspend output. You can suppress output by specifying the nonOutputProperties property and can specify multiple values of this property separated by commas. The value of the property specified by nonOutputProperties are output as the string specified by nonOutputString (default: ***).

Example of nonOutputProperties in DebugTrace.properties
nonOutputProperties = \
    org.lightsleep.helper.EntityInfo#columnInfos,\
    org.lightsleep.helper.EntityInfo#keyColumnInfos,\
    org.lightsleep.helper.ColumnInfo#entityInfo
4.2. Constant map and mapNameMap

A constant map is a map whose keys are numbers and whose values are constant names. If you specify the map name corresponding to the variable name in the mapNameMap property, the constant name corresponding to the numerical value will also be output.

Example of a constant map and mapNameMap in DebugTrace.properties
AppleBrand = \
    0: Apple.NO_BRAND,\
    1: Apple.AKANE,\
    2: Apple.AKIYO,\
    3: Apple.AZUSA,\
    4: Apple.YUKARI

mapNameMap = appleBrand:AppleBrand
Example of Java source
static public class Apple {
    public static final int NO_BRAND = 0;
    public static final int AKANE = 1;
    public static final int AKIYO = 2;
    public static final int AZUSA = 3;
    public static final int YUKARI = 4;
}
    ...

    int appleBrand = Apple.AKANE;
    DebugTrace.print("appleBrand", appleBrand);
    appleBrand = Apple.AKIYO;
    DebugTrace.print(" 2 appleBrand ", appleBrand);
    appleBrand = Apple.AZUSA;
    DebugTrace.print(" 3 example.appleBrand ", appleBrand);
    appleBrand = Apple.YUKARI;
    DebugTrace.print(" 4 example. appleBrand ", appleBrand);
Example of the log
2023-01-29 10:14:29.916+09:00 appleBrand = 1(Apple.AKANE) (ReadmeExample.java:18)
2023-01-29 10:14:29.916+09:00  2 appleBrand  = 2(Apple.AKIYO) (ReadmeExample.java:20)
2023-01-29 10:14:29.916+09:00  3 example.appleBrand  = 3(Apple.AZUSA) (ReadmeExample.java:22)
2023-01-29 10:14:29.916+09:00  4 example. appleBrand  = 4(Apple.YUKARI) (ReadmeExample.java:24)

5. Examples of using logging libraries

The logger name of DebugTrace is org.debugtrace.DebugTrace.

5.1. Example of logging.properties (JDK)
logging.properties
# logging.properties
handlers = java.util.logging.FileHandler
java.util.logging.FileHandler.level = FINEST
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format = %1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %5$s%n
java.util.logging.FileHandler.encoding = UTF-8
java.util.logging.FileHandler.pattern = /var/log/app/debugtrace.log
java.util.logging.FileHandler.append = false
org.debugtrace.DebugTrace.level = FINEST

-Djava.util.logging.config.file=<path>/logging.properties is required as Java startup option

5.2. Example of log4j.xml (Log4j)
log4j.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
  <appender name="traceAppender" class="org.apache.log4j.FileAppender">
    <param name="File" value="/var/log/app/debugtrace.log"/>
    <param name="Append" value="false" />
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p %t %m%n"/>
    </layout>
  </appender>

  <logger name="org.debugtrace.DebugTrace">
    <level value ="trace"/>
    <appender-ref ref="traceAppender"/>
  </logger>
</log4j:configuration>
5.3. Example of log4j2.xml (Log4j2)
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
  <Appenders>
    <File name="traceAppender" append="false" fileName="/var/log/app/debugtrace.log">
      <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level %thread %message%n"/>
    </File>
  </Appenders>

  <Loggers>
    <Logger name="org.debugtrace.DebugTrace" level="trace" additivity="false">
        <AppenderRef ref="traceAppender"/>
    </Logger>
  </Loggers>
</Configuration>
5.4. Example of logback.xml (SLF4J / Logback)
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <appender name="traceAppender" class="ch.qos.logback.core.FileAppender">
    <file>/var/log/app/debugtrace.log</file>
    <encoder>
      <pattern>%date{yyyy-MM-dd HH:mm:ss.SSS} %-5level %thread %message%n</pattern>
    </encoder>
  </appender>

  <logger name="org.debugtrace.DebugTrace" level="trace">
    <appender-ref ref="traceAppender"/>
  </logger>
</configuration>

6. Example of build.gradle description

build.gradle
repositories {
    mavenCentral()
}

dependencies {
    compile 'org.debugtrace:debugtrace:3.6.0'
}

7. License

© 2015 Masato Kokubo

9. Release Notes