NkTrace

More readable logs with indentation

License

License

Categories

Categories

Net Logging Application Layer Libs
GroupId

GroupId

net.kawinski.logging
ArtifactId

ArtifactId

nktrace
Last Version

Last Version

1.0.1.1
Release Date

Release Date

Type

Type

jar
Description

Description

NkTrace
More readable logs with indentation
Project URL

Project URL

https://github.com/NorbertKawinski/NkTrace
Project Organization

Project Organization

net.kawinski
Source Code Management

Source Code Management

https://github.com/NorbertKawinski/NkTrace

Download nktrace

How to add to project

<!-- https://jarcasting.com/artifacts/net.kawinski.logging/nktrace/ -->
<dependency>
    <groupId>net.kawinski.logging</groupId>
    <artifactId>nktrace</artifactId>
    <version>1.0.1.1</version>
</dependency>
// https://jarcasting.com/artifacts/net.kawinski.logging/nktrace/
implementation 'net.kawinski.logging:nktrace:1.0.1.1'
// https://jarcasting.com/artifacts/net.kawinski.logging/nktrace/
implementation ("net.kawinski.logging:nktrace:1.0.1.1")
'net.kawinski.logging:nktrace:jar:1.0.1.1'
<dependency org="net.kawinski.logging" name="nktrace" rev="1.0.1.1">
  <artifact name="nktrace" type="jar" />
</dependency>
@Grapes(
@Grab(group='net.kawinski.logging', module='nktrace', version='1.0.1.1')
)
libraryDependencies += "net.kawinski.logging" % "nktrace" % "1.0.1.1"
[net.kawinski.logging/nktrace "1.0.1.1"]

Dependencies

compile (1)

Group / Artifact Type Version
org.slf4j : slf4j-api jar 2.0.0-alpha1

test (2)

Group / Artifact Type Version
junit : junit jar 4.13
ch.qos.logback : logback-classic jar 1.3.0-alpha5

Project Modules

There are no modules declared in this project.

NkTrace

NkTrace is a Java library for making deep stack traces easier to read in the log files.
It's mainly done by wrapping methods in NkTrace blocks.

try(NkTrace trace = NkTrace.info(logger)) { 
    logger.info("Some code here...");
}

Such block automatically creates "entry" and "exit" log entries.
Additionally, all logs inside this block will be automatically indented to easily follow the span of the function.
With NkTrace, the logs will look like:

 INFO >> ExampleTest.example:42
 INFO    Some code here...
 INFO << ExampleTest.example:42

You can see more detailed examples in later sections of this readme.
To see an example project using NkTrace, check out this repository:
https://github.com/NorbertKawinski/NkTraceExample

Installation

Add NkTrace dependency

To start using NkTrace, we need to add NkTrace as a dependency.

You can download the binary yourself and add it manually to the classpath
or use a dependency manager (like Maven or Gradle).

Manual installation

Pick a release from the releases section

Maven

<dependency>
    <groupId>net.kawinski.logging</groupId>
    <artifactId>nktrace</artifactId>
    <version>${nktrace_version}</version>
    <scope>compile</scope>
</dependency>

Gradle

dependencies {
    implementation group: "net.kawinski.logging", name: "nktrace", version: "${nktrace_version}"
}

Add SLF4J-compatible logging framework

NkTrace isn't a standalone library.
Since NkTrace depends on SLF4J, you need to choose your preferred logging framework.

Not all SLF4J-compatible frameworks works well with NkTrace, because it requires:

  • MDC (Mapped Diagnostic Context) support required for indentation feature
  • (Optional) Marker support required if you want to use custom entry/exit message patterns

Logback and Log4j implement all these features.
Before using any other logging framework, please confirm the support for MDC and Markers.

Setting up standard formatter (Logback example)

To make the indentation work, you'll need to configure the message format to include indentation from the MDC.

This section will show you Logback example.
If you are using any other logging framework, check its formatter documentation.

Create src/main/resources/logback.xml file:

<configuration>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>%date [%thread] %5level %mdc{indent}%msg \(%file:%line\) %n</Pattern>
        </layout>
    </appender>
    <root level="all">
        <appender-ref ref="CONSOLE"/>
    </root>
</configuration>

Or, if you'd rather like to configure NkTrace programmatically:

final LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();

final PatternLayoutEncoder ple = new PatternLayoutEncoder();
ple.setPattern("%date [%thread] %5level %mdc{indent}%msg \\(%file:%line\\)%n");
ple.setContext(lc);
ple.start();

final ConsoleAppender<ILoggingEvent> consoleAppender = new ConsoleAppender<>();
consoleAppender.setEncoder(ple);
consoleAppender.setContext(lc);
consoleAppender.start();

final ch.qos.logback.classic.Logger rootLogger = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
rootLogger.detachAndStopAllAppenders();
rootLogger.addAppender(consoleAppender);
rootLogger.setLevel(Level.ALL);

Note: This readme used the following (simplified) layout format:

%5level %mdc{indent}%msg%n

(Optional) Setting up custom formatter (Logback example)

Depending on your setup of the pattern layout, you might want to display entry/exit logs differently.
It's certainly possible because NkTrace uses special markers NkTraceEntry and NkTraceExit for its messages.
Thanks to this, you can apply different log format only for these messages.

Since Logback doesn't allow setting different layouts based on the marker out of the box, we have to do it ourselves.
Please copy the NkPatternLayout class to your project. This class is located in test/java/net/kawinski/logging/utils package
This class holds 3 pattern layouts inside and switches on them based on the marker in the logging event.

All that's left is XML appender configuration:

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
        <layout class="net.kawinski.logging.utils.NkPatternLayout">
            <entryPattern>%5level %mdc{indent}Entering %method in %class{0} %msg .\(%file:%line\)%n</entryPattern>
            <regularPattern>%5level %mdc{indent}%msg .\(%file:%line\)%n</regularPattern>
            <exitPattern>%5level %mdc{indent}Exiting %method in %class{0} %msg .\(%file:%line\)%n</exitPattern>
        </layout>
    </encoder>
</appender>

Example 1

Following code presents the basic features of NkTrace

private void example01() {
    try (final NkTrace trace = NkTrace.info(logger)) {
        logger.info("Inside example01");
        example01A();
        example01B();
    }
}

private void example01A() {
    try (final NkTrace trace = NkTrace.debug(logger)) {
        logger.debug("Inside 01A");
    }
}

private void example01B() {
    try (final NkTrace trace = NkTrace.trace(logger)) {
        logger.trace("Inside 01B");
        logger.debug("Before 01C");
        example01C();
        logger.debug("After 01C");
    }
}

private void example01C() {
    try (final NkTrace trace = NkTrace.trace(logger)) {
        logger.trace("Inside 01C");
    }
}

calling example01 produces logs similar to:

 INFO >> ExampleTest.example01:26
 INFO    Inside example01
DEBUG    >> ExampleTest.example01A:34
DEBUG       Inside 01A
DEBUG    << ExampleTest.example01A:34
TRACE    >> ExampleTest.example01B:40
TRACE       Inside 01B
DEBUG       Before 01C
TRACE       >> ExampleTest.example01C:49
TRACE          Inside 01C
TRACE       << ExampleTest.example01C:49
DEBUG       After 01C
TRACE    << ExampleTest.example01B:40
 INFO << ExampleTest.example01:26

As you can see, each function is marked with >> and << entries along with inner logs being indented.

Example 2

Following code shows how to add custom messages to entry/exit logs.

private void example02() {
    try (final NkTrace trace = NkTrace.trace(logger)) {
        logger.info("Received 1: {}", myMultiply1(3.0, 6.0));
        logger.info("Received 2: {}", myMultiply2(3.0, 6.0));
    }
}

private double myMultiply1(final double a, final double b) {
    try (final NkTrace trace = NkTrace.debug(logger, "a: {}, b: {}", a, b)) {
        logger.debug("You can log the return value into the exit trace instead of logging another line");
        final double result = a * b;
        trace.returning(result); // instead of logger.info("Returning({})", result);
        return result;
    }
}

private double myMultiply2(final double a, final double b) {
    try (final NkTrace trace = NkTrace.debug(logger, "a: {}, b: {}", a, b)) {
        logger.debug("You can shorten exit trace and return value into a single line");
        return trace.returning(a * b);
    }
}

calling example02 produces logs similar to:

TRACE >> ExampleTest.example02:55
DEBUG    >> ExampleTest.myMultiply1:62 a: 3.0, b: 6.0
DEBUG       You can log the return value into the exit trace instead of logging another line
DEBUG    << ExampleTest.myMultiply1:62 returning(18.0)
 INFO    Received 1: 18.0
DEBUG    >> ExampleTest.myMultiply2:71 a: 3.0, b: 6.0
DEBUG       You can shorten exit trace and return value into a single line
DEBUG    << ExampleTest.myMultiply2:71 returning(18.0)
 INFO    Received 2: 18.0
TRACE << ExampleTest.example02:55

License

MIT

Versions

Version
1.0.1.1