Skip to content

Commit

Permalink
[FIXED JENKINS-21386] Allow reordering loggers, use first with matchi…
Browse files Browse the repository at this point in the history
…ng name.
  • Loading branch information
daniel-beck committed Jan 15, 2014
1 parent 4ace130 commit bd6b999
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 6 deletions.
35 changes: 32 additions & 3 deletions core/src/main/java/hudson/logging/LogRecorder.java
Expand Up @@ -84,14 +84,23 @@ public class LogRecorder extends AbstractModelObject implements Saveable {

public final CopyOnWriteList<Target> targets = new CopyOnWriteList<Target>();

private transient /*almost final*/ RingBufferLogHandler handler = new RingBufferLogHandler() {
@Restricted(NoExternalUse.class)
transient /*almost final*/ RingBufferLogHandler handler = new RingBufferLogHandler() {
@Override
public void publish(LogRecord record) {
for (Target t : targets) {
if(t.includes(record)) {
Boolean match = t.matches(record);
if (match == null) {
// domain does not match, so continue looking
continue;
}

if (match.booleanValue()) {
// first logger in configured order that matches name
// has sufficient log level
super.publish(record);
return;
}
return;
}
}
};
Expand Down Expand Up @@ -123,6 +132,11 @@ public Level getLevel() {
return Level.parse(String.valueOf(level));
}

public String getName() {
return name;
}

@Deprecated
public boolean includes(LogRecord r) {
if(r.getLevel().intValue() < level)
return false; // below the threshold
Expand All @@ -136,6 +150,21 @@ public boolean includes(LogRecord r) {
return rest.startsWith(".") || rest.length()==0;
}

public Boolean matches(LogRecord r) {
boolean levelSufficient = r.getLevel().intValue() >= level;
if (name.length() == 0) {
return Boolean.valueOf(levelSufficient); // include if level matches
}
String logName = r.getLoggerName();
if(logName==null || !logName.startsWith(name))
return null; // not in the domain of this logger
String rest = logName.substring(name.length());
if (rest.startsWith(".") || rest.length()==0) {
return Boolean.valueOf(levelSufficient); // include if level matches
}
return null;
}

public Logger getLogger() {
if (logger == null) {
logger = Logger.getLogger(name);
Expand Down
Expand Up @@ -40,7 +40,7 @@ THE SOFTWARE.
description="${%List of loggers and the log levels to record}"
help="/help/LogRecorder/logger.html">
<j:set var="instance" value="${null}" />
<f:repeatable var="instance" items="${it.targets}" name="targets">
<f:repeatable var="instance" items="${it.targets}" name="targets" header="Logger">
<table width="100%">
<tr>
<th style="white-space:nowrap;">
Expand Down
65 changes: 63 additions & 2 deletions core/src/test/java/hudson/logging/LogRecorderTest.java
Expand Up @@ -42,10 +42,71 @@ public class LogRecorderTest {
assertTrue(includes("", "hudson.model.Hudson"));
}

private static boolean includes(String target, String logger) {
LogRecord r = new LogRecord(Level.INFO, "whatever");
@Test public void targetMatches() {
assertTrue(matches("hudson", "hudson"));
assertFalse(matches("hudson", "hudson", Level.FINE));
assertNull(matches("hudson", "hudsone"));
assertNull(matches("hudson", "hudso"));
assertTrue(matches("hudson", "hudson.model.Hudson"));
assertFalse(matches("hudson", "hudson.model.Hudson", Level.FINE));
assertNull(matches("hudson", "jenkins.model.Jenkins"));
assertTrue(matches("", "hudson.model.Hudson"));
assertFalse(matches("", "hudson.model.Hudson", Level.FINE));
}

@Test public void testSpecificExclusion() {
LogRecorder lr = new LogRecorder("foo");

LogRecorder.Target targetH = new LogRecorder.Target("foo.bar", Level.SEVERE);
LogRecorder.Target targetM = new LogRecorder.Target("foo", Level.INFO);
LogRecorder.Target targetL = new LogRecorder.Target("", Level.FINE);

lr.targets.add(targetH);
lr.targets.add(targetM);
lr.targets.add(targetL);

LogRecord r1h = createLogRecord("foo.bar.baz", Level.INFO, "hidden");
LogRecord r1v = createLogRecord("foo.bar.baz", Level.SEVERE, "visible");
LogRecord r2h = createLogRecord("foo.bar", Level.INFO, "hidden");
LogRecord r2v = createLogRecord("foo.bar", Level.SEVERE, "hidden");
LogRecord r3h = createLogRecord("foo", Level.FINE, "hidden");
LogRecord r3v = createLogRecord("foo", Level.INFO, "visible");
LogRecord r4v = createLogRecord("baz", Level.INFO, "visible");
lr.handler.publish(r1h);
lr.handler.publish(r1v);
lr.handler.publish(r2h);
lr.handler.publish(r2v);
lr.handler.publish(r3v);
lr.handler.publish(r3h);
lr.handler.publish(r4v);

assertTrue(lr.handler.getView().contains(r1v));
assertFalse(lr.handler.getView().contains(r1h));
assertFalse(lr.handler.getView().contains(r2h));
assertTrue(lr.handler.getView().contains(r2v));
assertFalse(lr.handler.getView().contains(r3h));
assertTrue(lr.handler.getView().contains(r3v));
assertTrue(lr.handler.getView().contains(r4v));
}

private static LogRecord createLogRecord(String logger, Level level, String message) {
LogRecord r = new LogRecord(level, message);
r.setLoggerName(logger);
return r;
}

private static boolean includes(String target, String logger) {
LogRecord r = createLogRecord(logger, Level.INFO, "whatever");
return new LogRecorder.Target(target, Level.INFO).includes(r);
}

private static Boolean matches(String target, String logger) {
return matches(target, logger, Level.INFO);
}

private static Boolean matches(String target, String logger, Level loggerLevel) {
LogRecord r = createLogRecord(logger, loggerLevel, "whatever");
return new LogRecorder.Target(target, Level.INFO).matches(r);
}

}

0 comments on commit bd6b999

Please sign in to comment.