Skip to content

Commit 059f3ae

Browse files
committed
Revamp AbstractLogger in log4j-sdk
In order for Log4j Core 3.x not to depend on the utility classes in Log4j API 2.x, we provide a new `AbstractLogger` in `log4j-sdk`.
1 parent ed9f711 commit 059f3ae

File tree

17 files changed

+4745
-85
lines changed

17 files changed

+4745
-85
lines changed

log4j-async-logger/pom.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,21 @@
2828
<name>Apache Log4j Async Logger</name>
2929
<description>Alternative implementation of logger that uses LMAX Disruptor.</description>
3030

31+
<properties>
32+
<bnd-extra-package-options>
33+
<!-- JSpecify is optional at runtime -->
34+
org.jspecify.annotations.*;resolution:=optional
35+
</bnd-extra-package-options>
36+
</properties>
37+
3138
<dependencies>
3239

40+
<dependency>
41+
<groupId>org.jspecify</groupId>
42+
<artifactId>jspecify</artifactId>
43+
<scope>provided</scope>
44+
</dependency>
45+
3346
<dependency>
3447
<groupId>org.apache.logging.log4j</groupId>
3548
<artifactId>log4j-core</artifactId>

log4j-async-logger/src/main/java/org/apache/logging/log4j/async/logger/AsyncLogger.java

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,16 @@
3333
import org.apache.logging.log4j.core.impl.ContextDataFactory;
3434
import org.apache.logging.log4j.core.time.Clock;
3535
import org.apache.logging.log4j.core.time.NanoClock;
36+
import org.apache.logging.log4j.message.FlowMessageFactory;
3637
import org.apache.logging.log4j.message.Message;
3738
import org.apache.logging.log4j.message.MessageFactory;
38-
import org.apache.logging.log4j.spi.AbstractLogger;
39+
import org.apache.logging.log4j.sdk.logger.AbstractLogger;
3940
import org.apache.logging.log4j.spi.recycler.Recycler;
41+
import org.apache.logging.log4j.spi.recycler.RecyclerFactory;
4042
import org.apache.logging.log4j.util.StackLocatorUtil;
4143
import org.apache.logging.log4j.util.StringMap;
44+
import org.jspecify.annotations.NullMarked;
45+
import org.jspecify.annotations.Nullable;
4246

4347
/**
4448
* AsyncLogger is a logger designed for high throughput and low latency logging. It does not perform any I/O in the
@@ -59,6 +63,7 @@
5963
* and they will flush to disk at the end of each batch. This means that even with immediateFlush=false, there will
6064
* never be any items left in the buffer; all log events will all be written to disk in a very efficient manner.
6165
*/
66+
@NullMarked
6267
public class AsyncLogger extends Logger {
6368
// Implementation note: many methods in this class are tuned for performance. MODIFY WITH CARE!
6469
// Specifically, try to keep the hot methods to 35 bytecodes or less:
@@ -86,8 +91,10 @@ public class AsyncLogger extends Logger {
8691
final LoggerContext context,
8792
final String name,
8893
final MessageFactory messageFactory,
94+
final FlowMessageFactory flowMessageFactory,
95+
final RecyclerFactory recyclerFactory,
8996
final AsyncLoggerDisruptor loggerDisruptor) {
90-
super(context, name, messageFactory);
97+
super(context, name, messageFactory, flowMessageFactory, recyclerFactory);
9198
final Configuration configuration = context.getConfiguration();
9299
this.translatorRecycler = configuration
93100
.getRecyclerFactory()
@@ -107,7 +114,7 @@ public class AsyncLogger extends Logger {
107114
@Override
108115
protected void updateConfiguration(final Configuration newConfig) {
109116
nanoClock = newConfig.getNanoClock();
110-
includeLocation = newConfig.getLoggerConfig(name).isIncludeLocation();
117+
includeLocation = newConfig.getLoggerConfig(getName()).isIncludeLocation();
111118
super.updateConfiguration(newConfig);
112119
}
113120

@@ -154,21 +161,21 @@ public void logMessage(
154161
* @param level level at which the caller wants to log the message
155162
* @param marker message marker
156163
* @param message the log message
157-
* @param thrown a {@code Throwable} or {@code null}
164+
* @param throwable a {@code Throwable} or {@code null}
158165
*/
159166
@Override
160-
public void log(
167+
protected void doLog(
161168
final Level level,
162-
final Marker marker,
169+
final @Nullable Marker marker,
163170
final String fqcn,
164-
final StackTraceElement location,
171+
final @Nullable StackTraceElement location,
165172
final Message message,
166-
final Throwable thrown) {
173+
final @Nullable Throwable throwable) {
167174
// Implementation note: this method is tuned for performance. MODIFY WITH CARE!
168175

169176
final RingBufferLogEventTranslator translator = translatorRecycler.acquire();
170177
try {
171-
initTranslator(translator, fqcn, location, level, marker, message, thrown);
178+
initTranslator(translator, fqcn, location, level, marker, message, throwable);
172179
translator.updateThreadValues();
173180
publish(translator);
174181
} finally {
@@ -220,7 +227,7 @@ private void initTranslator(
220227

221228
translator.setBasicValues(
222229
this,
223-
name,
230+
getName(),
224231
marker,
225232
fqcn,
226233
level,
@@ -246,7 +253,7 @@ private void initTranslator(
246253

247254
translator.setBasicValues(
248255
this,
249-
name,
256+
getName(),
250257
marker,
251258
fqcn,
252259
level,

log4j-async-logger/src/main/java/org/apache/logging/log4j/async/logger/AsyncLoggerConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import org.apache.logging.log4j.plugins.Configurable;
3434
import org.apache.logging.log4j.plugins.Plugin;
3535
import org.apache.logging.log4j.plugins.PluginFactory;
36-
import org.apache.logging.log4j.spi.AbstractLogger;
36+
import org.apache.logging.log4j.sdk.logger.AbstractLogger;
3737
import org.apache.logging.log4j.util.Strings;
3838

3939
/**

log4j-async-logger/src/main/java/org/apache/logging/log4j/async/logger/AsyncLoggerContext.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222
import org.apache.logging.log4j.core.LoggerContext;
2323
import org.apache.logging.log4j.core.config.Configuration;
2424
import org.apache.logging.log4j.core.config.DefaultConfiguration;
25+
import org.apache.logging.log4j.message.FlowMessageFactory;
2526
import org.apache.logging.log4j.message.MessageFactory;
2627
import org.apache.logging.log4j.plugins.di.ConfigurableInstanceFactory;
28+
import org.apache.logging.log4j.spi.recycler.RecyclerFactory;
2729
import org.apache.logging.log4j.status.StatusLogger;
2830

2931
/**
@@ -78,8 +80,13 @@ private AsyncWaitStrategyFactory createAsyncWaitStrategyFactory() {
7880
}
7981

8082
@Override
81-
protected Logger newInstance(final LoggerContext ctx, final String name, final MessageFactory messageFactory) {
82-
return new AsyncLogger(ctx, name, messageFactory, loggerDisruptor);
83+
protected Logger newInstance(
84+
final LoggerContext ctx,
85+
final String name,
86+
final MessageFactory messageFactory,
87+
final FlowMessageFactory flowMessageFactory,
88+
final RecyclerFactory recyclerFactory) {
89+
return new AsyncLogger(ctx, name, messageFactory, flowMessageFactory, recyclerFactory, loggerDisruptor);
8390
}
8491

8592
@Override

log4j-async-logger/src/test/java/org/apache/logging/log4j/async/logger/AsyncLoggerEventTranslationExceptionTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import org.apache.logging.log4j.core.test.junit.LoggerContextSource;
3131
import org.apache.logging.log4j.message.Message;
3232
import org.apache.logging.log4j.message.ReusableSimpleMessage;
33-
import org.apache.logging.log4j.spi.AbstractLogger;
33+
import org.apache.logging.log4j.sdk.logger.AbstractLogger;
3434
import org.junit.jupiter.api.Tag;
3535
import org.junit.jupiter.api.Test;
3636
import org.junitpioneer.jupiter.SetSystemProperty;

log4j-core/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
com.lmax.disruptor.*;resolution:=optional,
4040
org.apache.commons.compress.*;resolution:=optional,
4141
org.fusesource.jansi;resolution:=optional,
42+
org.jspecify.annotations.*;resolution:=optional,
4243
<!-- Optional Java modules -->
4344
<!-- java.management -->
4445
java.lang.management;resolution:=optional,
@@ -73,6 +74,10 @@
7374
<groupId>org.apache.logging.log4j</groupId>
7475
<artifactId>log4j-plugins</artifactId>
7576
</dependency>
77+
<dependency>
78+
<groupId>org.apache.logging.log4j</groupId>
79+
<artifactId>log4j-sdk</artifactId>
80+
</dependency>
7681
<!-- The dependency on the plugin processor is only required to ensure the processor is built before core. We
7782
don't want the dependency to be included by consumers -->
7883
<dependency>

log4j-core/src/main/java/org/apache/logging/log4j/core/Logger.java

Lines changed: 29 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,15 @@
2828
import org.apache.logging.log4j.core.config.LoggerConfig;
2929
import org.apache.logging.log4j.core.config.ReliabilityStrategy;
3030
import org.apache.logging.log4j.core.filter.CompositeFilter;
31+
import org.apache.logging.log4j.message.FlowMessageFactory;
3132
import org.apache.logging.log4j.message.Message;
3233
import org.apache.logging.log4j.message.MessageFactory;
33-
import org.apache.logging.log4j.message.SimpleMessage;
34-
import org.apache.logging.log4j.spi.AbstractLogger;
34+
import org.apache.logging.log4j.sdk.logger.AbstractLogger;
35+
import org.apache.logging.log4j.spi.recycler.RecyclerFactory;
3536
import org.apache.logging.log4j.util.Strings;
3637
import org.apache.logging.log4j.util.Supplier;
38+
import org.jspecify.annotations.NullMarked;
39+
import org.jspecify.annotations.Nullable;
3740

3841
/**
3942
* The core implementation of the {@link org.apache.logging.log4j.Logger} interface. Besides providing an implementation
@@ -43,40 +46,36 @@
4346
* unit tests or bridging legacy Log4j 1.x code. Future versions of this class may or may not include the various
4447
* methods that are noted as not being part of the public API.
4548
*/
49+
@NullMarked
4650
public class Logger extends AbstractLogger implements Supplier<LoggerConfig> {
4751

4852
/**
4953
* Config should be consistent across threads.
5054
*/
5155
protected volatile PrivateConfig privateConfig;
5256

53-
// FIXME: ditto to the above
5457
private final LoggerContext context;
5558

5659
/**
5760
* The constructor.
5861
*
5962
* @param context The LoggerContext this Logger is associated with.
60-
* @param messageFactory The message factory.
6163
* @param name The name of the Logger.
64+
* @param messageFactory The message factory to use for logging methods.
65+
* @param flowMessageFactory The flow message factory to use for flow logging methods.
66+
* @param recyclerFactory The recycler to use for log builder instances.
6267
*/
63-
protected Logger(final LoggerContext context, final String name, final MessageFactory messageFactory) {
64-
super(name, messageFactory);
68+
protected Logger(
69+
final LoggerContext context,
70+
final String name,
71+
final MessageFactory messageFactory,
72+
final FlowMessageFactory flowMessageFactory,
73+
final RecyclerFactory recyclerFactory) {
74+
super(name, messageFactory, flowMessageFactory, recyclerFactory);
6575
this.context = context;
6676
privateConfig = new PrivateConfig(context.getConfiguration(), this);
6777
}
6878

69-
/**
70-
* This is used to construct an InternalLoggerContext, which makes SimpleLoggerContext conmpatible with core.
71-
* @param context the InternalLoggerContext.
72-
* @param name the Logger name.
73-
*/
74-
protected Logger(final LoggerContext context, final String name) {
75-
super(name);
76-
this.context = context;
77-
privateConfig = null;
78-
}
79-
8079
/**
8180
* This method is only used for 1.x compatibility. Returns the parent of this Logger. If it doesn't already exist
8281
* return a temporary Logger.
@@ -95,10 +94,7 @@ private Logger getParent(final PrivateConfig config) {
9594
}
9695
final String lcName = lc.getName();
9796
final MessageFactory messageFactory = getMessageFactory();
98-
if (context.hasLogger(lcName, messageFactory)) {
99-
return context.getLogger(lcName, messageFactory);
100-
}
101-
return new Logger(context, lcName, messageFactory);
97+
return context.getLogger(lcName, messageFactory);
10298
}
10399

104100
/**
@@ -149,35 +145,32 @@ protected boolean requiresLocation() {
149145
}
150146

151147
@Override
152-
public void logMessage(
153-
final String fqcn, final Level level, final Marker marker, final Message message, final Throwable t) {
154-
final Message msg = message == null ? new SimpleMessage(Strings.EMPTY) : message;
155-
final ReliabilityStrategy strategy = privateConfig.loggerConfig.getReliabilityStrategy();
156-
strategy.log(this, getName(), fqcn, marker, level, msg, t);
157-
}
158-
159-
@Override
160-
protected void log(
148+
protected void doLog(
161149
final Level level,
162-
final Marker marker,
150+
final @Nullable Marker marker,
163151
final String fqcn,
164-
final StackTraceElement location,
165-
final Message message,
166-
final Throwable throwable) {
152+
final @Nullable StackTraceElement location,
153+
final @Nullable Message message,
154+
final @Nullable Throwable throwable) {
167155
final ReliabilityStrategy strategy = privateConfig.loggerConfig.getReliabilityStrategy();
168156
strategy.log(this, getName(), fqcn, location, marker, level, message, throwable);
169157
}
170158

171159
@Override
172-
public boolean isEnabled(final Level level, final Marker marker, final String message, final Throwable t) {
173-
return privateConfig.filter(level, marker, message, t);
160+
public boolean isEnabled(final Level level, final Marker marker) {
161+
return privateConfig.filter(level, marker, null);
174162
}
175163

176164
@Override
177165
public boolean isEnabled(final Level level, final Marker marker, final String message) {
178166
return privateConfig.filter(level, marker, message);
179167
}
180168

169+
@Override
170+
public boolean isEnabled(final Level level, final Marker marker, final String message, final Throwable t) {
171+
return privateConfig.filter(level, marker, message, t);
172+
}
173+
181174
@Override
182175
public boolean isEnabled(final Level level, final Marker marker, final String message, final Object... params) {
183176
return privateConfig.filter(level, marker, message, params);

0 commit comments

Comments
 (0)