TestLogger.java
/*
* Copyright 2018 SPF4J.
*
* Licensed 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.
*/
package org.spf4j.test.log;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.EnumMap;
import java.util.Map;
import java.util.function.Supplier;
import javax.annotation.concurrent.ThreadSafe;
import org.slf4j.Logger;
import org.slf4j.Marker;
import org.spf4j.log.Level;
//CHECKSTYLE:OFF
import sun.misc.Contended;
//CHECKSTYLE:ON
/**
* @author Zoltan Farkas
*/
@ThreadSafe
public final class TestLogger implements Logger {
private final String name;
private final Supplier<LogConfig> cfgSource;
private final Map<Level, Supplier<LogConsumer>> consumers;
private static final class LogConfigConsumer {
private static final LogConfigConsumer NULL = new LogConfigConsumer(null, null);
private final LogConfig cfg;
private final LogConsumer consumer;
LogConfigConsumer(final LogConfig cfg, final LogConsumer consumer) {
this.cfg = cfg;
this.consumer = consumer;
}
}
@ThreadSafe
private final class ConsumerSupplier implements Supplier<LogConsumer> {
private final Level level;
@Contended
private volatile LogConfigConsumer cfgConsumer;
ConsumerSupplier(final Level level) {
this.level = level;
this.cfgConsumer = LogConfigConsumer.NULL;
}
@Override
@SuppressFBWarnings("NOS_NON_OWNED_SYNCHRONIZATION") //its a private class
public LogConsumer get() {
LogConfig nCfg = cfgSource.get();
LogConfigConsumer curCfgConsumer = cfgConsumer;
if (nCfg == curCfgConsumer.cfg) {
return curCfgConsumer.consumer;
} else {
synchronized (this) {
nCfg = cfgSource.get();
curCfgConsumer = cfgConsumer;
if (nCfg == curCfgConsumer.cfg) {
return curCfgConsumer.consumer;
} else {
LogConsumer nCons = nCfg.getLogConsumer(name, level);
cfgConsumer = new LogConfigConsumer(nCfg, nCons);
return nCons;
}
}
}
}
}
public TestLogger(final String name, final Supplier<LogConfig> configSource) {
this.name = name;
this.cfgSource = configSource;
this.consumers = new EnumMap<>(Level.class);
for (Level level : Level.values()) {
consumers.put(level, new ConsumerSupplier(level));
}
}
@Override
public String getName() {
return name;
}
public void log(final Level level, final Marker marker, final String msg, final Object... args) {
LogConsumer consumer = consumers.get(level).get();
if (consumer != null) {
consumer.accept(new TestLogRecordImpl(name, level, marker, msg, args));
}
}
@Override
public boolean isTraceEnabled() {
return consumers.get(Level.TRACE).get() != null;
}
@Override
public void trace(final String msg) {
log(Level.TRACE, null, msg);
}
@Override
public void trace(final String format, final Object arg) {
log(Level.TRACE, null, format, arg);
}
@Override
public void trace(final String format, final Object arg1, final Object arg2) {
log(Level.TRACE, null, format, arg1, arg2);
}
@Override
public void trace(final String format, final Object... arguments) {
log(Level.TRACE, null, format, arguments);
}
@Override
public void trace(final String msg, final Throwable t) {
log(Level.TRACE, null, msg, t);
}
@Override
public boolean isTraceEnabled(final Marker marker) {
return isTraceEnabled();
}
@Override
public void trace(final Marker marker, final String msg) {
log(Level.TRACE, marker, msg);
}
@Override
public void trace(final Marker marker, final String format, final Object arg) {
log(Level.TRACE, marker, format, arg);
}
@Override
public void trace(final Marker marker, final String format, final Object arg1, final Object arg2) {
log(Level.TRACE, marker, format, arg1, arg2);
}
@Override
public void trace(final Marker marker, final String format, final Object... argArray) {
log(Level.TRACE, marker, format, argArray);
}
@Override
public void trace(final Marker marker, final String msg, final Throwable t) {
log(Level.TRACE, marker, msg, t);
}
@Override
public boolean isDebugEnabled() {
return consumers.get(Level.DEBUG).get() != null;
}
@Override
public void debug(final String msg) {
log(Level.DEBUG, null, msg);
}
@Override
public void debug(final String format, final Object arg) {
log(Level.DEBUG, null, format, arg);
}
@Override
public void debug(final String format, final Object arg1, final Object arg2) {
log(Level.DEBUG, null, format, arg1, arg2);
}
@Override
public void debug(final String format, final Object... arguments) {
log(Level.DEBUG, null, format, arguments);
}
@Override
public void debug(final String msg, final Throwable t) {
log(Level.DEBUG, null, msg, t);
}
@Override
public boolean isDebugEnabled(final Marker marker) {
return isDebugEnabled();
}
@Override
public void debug(final Marker marker, final String msg) {
log(Level.DEBUG, marker, msg);
}
@Override
public void debug(final Marker marker, final String format, final Object arg) {
log(Level.DEBUG, marker, format, arg);
}
@Override
public void debug(final Marker marker, final String format, final Object arg1, final Object arg2) {
log(Level.DEBUG, marker, format, arg1, arg2);
}
@Override
public void debug(final Marker marker, final String format, final Object... arguments) {
log(Level.DEBUG, marker, format, arguments);
}
@Override
public void debug(final Marker marker, final String msg, final Throwable t) {
log(Level.DEBUG, marker, msg, t);
}
@Override
public boolean isInfoEnabled() {
return consumers.get(Level.INFO).get() != null;
}
@Override
public void info(final String msg) {
log(Level.INFO, null, msg);
}
@Override
public void info(final String format, final Object arg) {
log(Level.INFO, null, format, arg);
}
@Override
public void info(final String format, final Object arg1, final Object arg2) {
log(Level.INFO, null, format, arg1, arg2);
}
@Override
public void info(final String format, final Object... arguments) {
log(Level.INFO, null, format, arguments);
}
@Override
public void info(final String msg, final Throwable t) {
log(Level.INFO, null, msg, t);
}
@Override
public boolean isInfoEnabled(final Marker marker) {
return isInfoEnabled();
}
@Override
public void info(final Marker marker, final String msg) {
log(Level.INFO, marker, msg);
}
@Override
public void info(final Marker marker, final String format, final Object arg) {
log(Level.INFO, marker, format, arg);
}
@Override
public void info(final Marker marker, final String format, final Object arg1, final Object arg2) {
log(Level.INFO, marker, format, arg1, arg2);
}
@Override
public void info(final Marker marker, final String format, final Object... arguments) {
log(Level.INFO, marker, format, arguments);
}
@Override
public void info(final Marker marker, final String msg, final Throwable t) {
log(Level.INFO, marker, msg, t);
}
@Override
public boolean isWarnEnabled() {
return consumers.get(Level.WARN).get() != null;
}
@Override
public void warn(final String msg) {
log(Level.WARN, null, msg);
}
@Override
public void warn(final String format, final Object arg) {
log(Level.WARN, null, format, arg);
}
@Override
public void warn(final String format, final Object... arguments) {
log(Level.WARN, null, format, arguments);
}
@Override
public void warn(final String format, final Object arg1, final Object arg2) {
log(Level.WARN, null, format, arg1, arg2);
}
@Override
public void warn(final String msg, final Throwable t) {
log(Level.WARN, null, msg, t);
}
@Override
public boolean isWarnEnabled(final Marker marker) {
return isWarnEnabled();
}
@Override
public void warn(final Marker marker, final String msg) {
log(Level.WARN, marker, msg);
}
@Override
public void warn(final Marker marker, final String format, final Object arg) {
log(Level.WARN, marker, format, arg);
}
@Override
public void warn(final Marker marker, final String format, final Object arg1, final Object arg2) {
log(Level.WARN, marker, format, arg1, arg2);
}
@Override
public void warn(final Marker marker, final String format, final Object... arguments) {
log(Level.WARN, marker, format, arguments);
}
@Override
public void warn(final Marker marker, final String msg, final Throwable t) {
log(Level.WARN, marker, msg, t);
}
@Override
public boolean isErrorEnabled() {
return consumers.get(Level.ERROR).get() != null;
}
@Override
public void error(final String msg) {
log(Level.ERROR, null, msg);
}
@Override
public void error(final String format, final Object arg) {
log(Level.ERROR, null, format, arg);
}
@Override
public void error(final String format, final Object arg1, final Object arg2) {
log(Level.ERROR, null, format, arg1, arg2);
}
@Override
public void error(final String format, final Object... arguments) {
log(Level.ERROR, null, format, arguments);
}
@Override
public void error(final String msg, final Throwable t) {
log(Level.ERROR, null, msg, t);
}
@Override
public boolean isErrorEnabled(final Marker marker) {
return isErrorEnabled();
}
@Override
public void error(final Marker marker, final String msg) {
log(Level.ERROR, marker, msg);
}
@Override
public void error(final Marker marker, final String format, final Object arg) {
log(Level.ERROR, marker, format, arg);
}
@Override
public void error(final Marker marker, final String format, final Object arg1, final Object arg2) {
log(Level.ERROR, marker, format, arg1, arg2);
}
@Override
public void error(final Marker marker, final String format, final Object... arguments) {
log(Level.ERROR, marker, format, arguments);
}
@Override
public void error(final Marker marker, final String msg, final Throwable t) {
log(Level.ERROR, marker, msg, t);
}
@Override
public String toString() {
return "TestLogger{" + "name=" + name + '}';
}
}