Skip to content

Commit

Permalink
Refresh all alias loggers when any change. Resolves #59
Browse files Browse the repository at this point in the history
  • Loading branch information
jhannes committed Nov 22, 2021
1 parent 1ee0e06 commit 900e10d
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 30 deletions.
93 changes: 66 additions & 27 deletions logevents/src/main/java/org/logevents/LogEventFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.ServiceLoader;
import java.util.TreeMap;
import java.util.function.Supplier;
import java.util.stream.Stream;

/**
* LogEventFactory holds all active loggers and lets you set the
Expand Down Expand Up @@ -64,20 +65,30 @@ public synchronized static LogEventFactory getInstance() {
private final Map<String, LogEventObserver> observers = new HashMap<>();

private final LoggerDelegator rootLogger = LoggerDelegator.rootLogger();
private final Map<String, LoggerDelegator> loggerCache = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
private final Map<String, LoggerDelegator> loggerCache = new TreeMap<>();
private final Map<String, LoggerDelegator> loggerAliasCache = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);

@Override
public synchronized LoggerConfiguration getLogger(String name) {
if (name == null || name.equals(Logger.ROOT_LOGGER_NAME)) {
return rootLogger;
}
if (!loggerCache.containsKey(name)) {
if (loggerCache.containsKey(name)) {
return loggerCache.get(name);
}

if (loggerAliasCache.containsKey(name)) {
LoggerDelegator logger = loggerAliasCache.get(name).withName(name);
loggerCache.put(name, logger);
return logger;
} else {
int lastPeriodPos = name.lastIndexOf('.');
LoggerDelegator parent = (LoggerDelegator)(lastPeriodPos < 0 ? rootLogger : getLogger(name.substring(0, lastPeriodPos)));
loggerCache.put(name, parent.getChildLogger(name));
LoggerDelegator logger = parent.getChildLogger(name);
loggerCache.put(name, logger);
loggerAliasCache.put(name, logger);
return logger;
}

return loggerCache.get(name).withName(name);
}

/**
Expand Down Expand Up @@ -109,25 +120,63 @@ public LogEventFilter setFilter(Logger logger, LogEventFilter filter) {
LogEventFilter oldFilter = ((LoggerDelegator)logger).getOwnFilter();
((LoggerDelegator)logger).setFilter(filter);
refreshLoggers((LoggerDelegator)logger);
aliasLoggers(logger).forEach(alias -> {
alias.setFilter(filter);
refreshLoggers(alias);
});
return oldFilter;
}

private void refreshLoggers(LoggerDelegator logger) {
logger.refresh();
loggerCache.values().stream().filter(l -> l.hasParent(logger)).forEach(this::refreshLoggers);
/**
* Sets the observer that should be used to receive LogEvents for this logger
* and children.
*
* @param logger The logger to set
* @param observer The nullable observer. Use {@link CompositeLogEventObserver} to register more than one observer
* @param inheritParentObserver If true, observers set on the observers will also receive log events
* @return The previous observer. Useful if you want to temporarily set the observer
*/
public LogEventObserver setObserver(Logger logger, LogEventObserver observer, boolean inheritParentObserver) {
LogEventObserver oldObserver = ((LoggerDelegator)logger).setObserver(observer, inheritParentObserver);
refreshLoggers((LoggerDelegator)logger);
aliasLoggers(logger).forEach(alias -> {
alias.setObserver(observer, inheritParentObserver);
refreshLoggers(alias);
});
return oldObserver;
}

public void setRootObserver(LogEventObserver observer) {
setObserver(getRootLogger(), observer, true);
public LogEventObserver setRootObserver(LogEventObserver observer) {
return setObserver(getRootLogger(), observer, true);
}

public void setObserver(String loggerName, LogEventObserver observer) {
setObserver(getLogger(loggerName), observer);
}

public void setObserver(LoggerConfiguration logger, LogEventObserver observer) {
logger.replaceObserver(observer);
public LogEventObserver setObserver(LoggerConfiguration logger, LogEventObserver observer) {
LogEventObserver oldObserver = logger.replaceObserver(observer);
refreshLoggers((LoggerDelegator) logger);
aliasLoggers(logger).forEach(alias -> {
alias.replaceObserver(observer);
refreshLoggers(alias);
});
return oldObserver;
}

private void refreshLoggers(LoggerDelegator logger) {
logger.refresh();
childLoggers(logger).forEach(this::refreshLoggers);
}

private Stream<LoggerDelegator> childLoggers(LoggerDelegator l) {
return loggerCache.values().stream().filter(l2 -> l2.hasParent(l));
}

private Stream<LoggerDelegator> aliasLoggers(Logger logger) {
return loggerCache.values().stream()
.filter(l -> l != logger)
.filter(l -> l.getName().equalsIgnoreCase(logger.getName()));
}

public Collection<String> getObserverNames() {
Expand All @@ -154,20 +203,6 @@ public LogEventObserver tryGetObserver(String observerName) {
return observers.get(observerName);
}

/**
* Sets the observer that should be used to receive LogEvents for this logger
* and children.
*
* @param logger The logger to set
* @param observer The nullable observer. Use {@link CompositeLogEventObserver} to register more than one observer
* @param inheritParentObserver If true, observers set on the observers will also receive log events
* @return The previous observer. Useful if you want to temporarily set the observer
*/
public LogEventObserver setObserver(Logger logger, LogEventObserver observer, boolean inheritParentObserver) {
LogEventObserver oldObserver = ((LoggerDelegator)logger).setObserver(observer, inheritParentObserver);
refreshLoggers((LoggerDelegator)logger);
return oldObserver;
}

/**
* Adds a new nullable observer to the current observers for the root logger
Expand All @@ -186,9 +221,13 @@ public void addObserver(String loggerName, LogEventObserver observer) {
/**
* Adds a new nullable observer to the current observers for the specified logger
*/
private void addObserver(Logger logger, LogEventObserver observer) {
public void addObserver(Logger logger, LogEventObserver observer) {
((LoggerDelegator)logger).addObserver(observer);
refreshLoggers((LoggerDelegator)logger);
aliasLoggers(logger).forEach(alias -> {
alias.addObserver(observer);
refreshLoggers(alias);
});
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public interface LoggerConfiguration extends Logger, LocationAwareLogger {
*/
String getObserver();

void replaceObserver(LogEventObserver observer);
LogEventObserver replaceObserver(LogEventObserver observer);

boolean isConfigured();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -573,8 +573,11 @@ public void addObserver(LogEventObserver observer) {
this.ownObserver = CompositeLogEventObserver.combine(observer, ownObserver);
}

public void replaceObserver(LogEventObserver observer) {
@Override
public LogEventObserver replaceObserver(LogEventObserver observer) {
LogEventObserver oldObserver = this.ownObserver;
this.ownObserver = observer;
return oldObserver;
}

public LoggerDelegator getChildLogger(String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

import java.io.IOException;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;

public class ExpectedLogEventsRuleTest {
Expand Down Expand Up @@ -65,7 +66,7 @@ public void shouldFailWhenNotMatchedExactly() {
MatcherAssert.assertThat(e.getMessage(), CoreMatchers.containsString("This is a nice test"));
}
}

@Test
public void shouldFailWhenArgumentsNotMatched() {
rule.expectMatch(expect -> expect
Expand Down Expand Up @@ -102,8 +103,10 @@ public void shouldFailWhenArgumentsOutOfBound() {
public void shouldMatchException() {
rule.expect(ExpectedLogEventsRuleTest.class, Level.WARN, "This is a nice test",
new IOException("Uh oh!"));
assertEquals("ExpectedLogEventsRule{matchers=1, events=[]}", rule.toString());

logger.warn("This is a {} test", "nice", new IOException("Uh oh!"));
assertEquals("ExpectedLogEventsRule{matchers=1, events=[LogEvent{org.logevents.extend.junit.ExpectedLogEventsRuleTest,WARN,This is a {} test}]}", rule.toString());
rule.verifyCompletion();
}

Expand Down

0 comments on commit 900e10d

Please sign in to comment.