Skip to content

Commit

Permalink
+ added MDC context display feature
Browse files Browse the repository at this point in the history
  • Loading branch information
q3769 committed Feb 14, 2024
1 parent 3f3a7d0 commit 4c8f44a
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 15 deletions.
7 changes: 6 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

<groupId>io.github.elf4j</groupId>
<artifactId>elf4j-engine</artifactId>
<version>15.0.0</version>
<version>15.1.0</version>
<packaging>jar</packaging>
<name>elf4j-engine</name>
<description>A stand-alone Java log engine implementing the ELF4J (Easy Logging Facade for Java) API</description>
Expand Down Expand Up @@ -79,6 +79,11 @@
<artifactId>dsl-json</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.11</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/elf4j/engine/NativeLogServiceProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import java.util.function.Function;
import javax.annotation.Nullable;
import lombok.NonNull;
import org.slf4j.MdcAdapterInitializer;

/**
*
Expand Down Expand Up @@ -87,6 +88,7 @@ public NativeLogServiceProvider(@NonNull Class<?> serviceAccessClass) {
@NonNull Level defaultLoggerLevel,
@NonNull Class<?> serviceAccessClass,
@NonNull NativeLogServiceProvider.NativeLoggerServiceFactory nativeLoggerServiceFactory) {
MdcAdapterInitializer.initialize();
this.defaultLoggerLevel = defaultLoggerLevel;
this.serviceAccessClass = serviceAccessClass;
this.nativeLoggerServiceFactory = nativeLoggerServiceFactory;
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/elf4j/engine/service/pattern/ContextElement.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package elf4j.engine.service.pattern;

import elf4j.engine.service.LogEvent;
import java.util.NoSuchElementException;
import lombok.NonNull;
import org.slf4j.MDC;

public class ContextElement implements PatternElement {
final String key;

public ContextElement(String key) {
this.key = key;
}

@Override
public boolean includeCallerDetail() {
return false;
}

public static @NonNull ContextElement from(String patternSegment) {
return new ContextElement(PatternElements.getPatternElementDisplayOption(patternSegment)
.orElseThrow(() -> new NoSuchElementException("No key configured in 'context' pattern element")));
}
/**
*
* @param logEvent entire log content data source to render
* @param target logging text aggregator of the final log message
*/
@Override
public void render(LogEvent logEvent, @NonNull StringBuilder target) {
String value = MDC.get(key);
target.append(value == null ? "" : value);
}
}
12 changes: 6 additions & 6 deletions src/main/java/elf4j/engine/service/pattern/JsonElement.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,13 @@
import java.nio.charset.StandardCharsets;
import java.time.OffsetDateTime;
import java.time.ZoneId;
import java.util.Arrays;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.*;
import java.util.stream.Collectors;
import lombok.Builder;
import lombok.NonNull;
import lombok.ToString;
import lombok.Value;
import org.slf4j.MDC;

/**
*
Expand Down Expand Up @@ -112,11 +110,12 @@ public void render(LogEvent logEvent, @NonNull StringBuilder target) {
@CompiledJson
static class JsonLogEntry {
OffsetDateTime timestamp;
LogEvent.ThreadValue callerThread;
String level;
CharSequence message;
LogEvent.ThreadValue callerThread;
String callerClass;
LogEvent.StackFrameValue callerDetail;
Map<String, String> context;
CharSequence message;
CharSequence exception;

static JsonLogEntry from(@NonNull LogEvent logEvent, @NonNull JsonElement jsonPattern) {
Expand All @@ -128,6 +127,7 @@ static JsonLogEntry from(@NonNull LogEvent logEvent, @NonNull JsonElement jsonPa
.callerDetail(
jsonPattern.includeCallerDetail ? Objects.requireNonNull(logEvent.getCallerFrame()) : null)
.message(logEvent.getResolvedMessage())
.context(MDC.getCopyOfContextMap())
.exception(
logEvent.getThrowable() == null
? null
Expand Down
12 changes: 8 additions & 4 deletions src/main/java/elf4j/engine/service/pattern/PatternElements.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package elf4j.engine.service.pattern;

import java.util.EnumSet;
import java.util.Arrays;
import java.util.Optional;
import lombok.NonNull;

class PatternElements {
private static final EnumSet<PredefinedPatternElement> PREDEFINED_PATTERN_ELEMENT_TYPES =
EnumSet.allOf(PredefinedPatternElement.class);

private PatternElements() {}

Expand All @@ -21,7 +19,7 @@ static Optional<String> getPatternElementDisplayOption(@NonNull String patternEl
}

static PatternElement parsePredefinedPatternELement(String predefinedPatternElement) {
return PREDEFINED_PATTERN_ELEMENT_TYPES.stream()
return Arrays.stream(PredefinedPatternElement.values())
.filter(type -> type.isTargetTypeOf(predefinedPatternElement))
.findFirst()
.orElseThrow(() ->
Expand Down Expand Up @@ -124,6 +122,12 @@ PatternElement parse(String patternElement) {
PatternElement parse(String patternElement) {
return SystemEnvironmentElement.from(patternElement);
}
},
CONTEXT {
@Override
PatternElement parse(String patternElement) {
return ContextElement.from(patternElement);
}
};

/**
Expand Down
16 changes: 14 additions & 2 deletions src/main/java/elf4j/engine/service/writer/ConseqWriterGroup.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import java.util.stream.Collectors;
import lombok.NonNull;
import lombok.ToString;
import org.slf4j.MDC;

/**
* In general, log events are asynchronously written/rendered in parallel by multiple concurrent threads. However,
Expand Down Expand Up @@ -126,16 +127,27 @@ public Level getThresholdOutputLevel() {
@Override
public void write(@NonNull LogEvent logEvent) {
conseqExecutor.execute(
() -> {
withMdcContext(() -> {
if (writers.size() == 1) {
writers.get(0).write(logEvent);
return;
}
writers.stream().parallel().forEach(writer -> writer.write(logEvent));
},
}),
logEvent.getCallerThread().getId());
}

private static Runnable withMdcContext(Runnable task) {
Map<String, String> copyOfContextMap = MDC.getCopyOfContextMap();
return (copyOfContextMap == null)
? task
: () -> {
MDC.clear();
MDC.setContextMap(copyOfContextMap);
task.run();
};
}

@Override
public boolean includeCallerDetail() {
if (includeCallerDetail == null) {
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/org/slf4j/MdcAdapterInitializer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.slf4j;

import org.slf4j.helpers.BasicMDCAdapter;
import org.slf4j.helpers.NOPMDCAdapter;
import org.slf4j.spi.MDCAdapter;

public class MdcAdapterInitializer {
private MdcAdapterInitializer() {}

public static void initialize() {
MDCAdapter byOtherSlf4jProvider = MDC.mdcAdapter;
if (byOtherSlf4jProvider == null || byOtherSlf4jProvider instanceof NOPMDCAdapter) {
MDC.mdcAdapter = new BasicMDCAdapter();
}
}
}
2 changes: 2 additions & 0 deletions src/test/java/elf4j/engine/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,13 @@
import elf4j.Logger;
import elf4j.engine.service.NativeLogServiceManager;
import java.util.function.Supplier;
import org.slf4j.MDC;

public class Main {
static Logger logger = Logger.instance();

public static void main(String[] args) {
MDC.put("ctx-key", "ctx-value");
logger.log("Hello, world!");
logger.atTrace().log("It's a beautiful day");
Logger info = logger.atInfo();
Expand Down
4 changes: 2 additions & 2 deletions src/test/resources/elf4j-test.properties
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ level@org.apache=error
### Writer out stream type - stdout/stderr, default to stdout
#stream=stderr
### Overriding default writer pattern (optional)
#pattern={timestamp:yyyy-MM-dd HH:mm:ss} {level} {thread} {class:full} - {message}
#pattern={timestamp:yyyy-MM-dd HH:mm:ss} {level} {thread} {class:full} [{context:ctx-key}] - {message}
#pattern={json:caller-thread,caller-detail,pretty}
pattern={json:caller-thread}
pattern={json:caller-thread,caller-detail}
#pattern={json}
### Max concurrency to process log events from all caller threads
#concurrency=20

0 comments on commit 4c8f44a

Please sign in to comment.