Created
December 20, 2011 16:03
-
-
Save anonymous/1502077 to your computer and use it in GitHub Desktop.
Logback files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CustomFilter extends Filter<ILoggingEvent> { | |
private Set<String> customizedUsersSet; | |
public FilterReply decide(ILoggingEvent event) { | |
//deny anything but a user filtered by CustomTurboFilter | |
if (!isStarted() || customizedUsersSet == null) | |
return FilterReply.DENY; | |
String user = MDC.get("userId"); | |
if (user == null) | |
return FilterReply.DENY; | |
return customizedUsersSet.contains(user) ? FilterReply.NEUTRAL : FilterReply.DENY; | |
} | |
public void start() { | |
//FIXME is this safe? Joran's sequential processing seems to make it so | |
Iterator<TurboFilter> iterator = ((LoggerContext) getContext()).getTurboFilterList().iterator(); | |
while (iterator.hasNext()) { | |
TurboFilter tf = iterator.next(); | |
if (tf instanceof CustomTurboFilter) { | |
customizedUsersSet = ((CustomTurboFilter) tf).getCustomizedUsersSet(); | |
addInfo("Allowed users: " + customizedUsersSet); | |
break; | |
} | |
} | |
if (customizedUsersSet == null) | |
addWarn("No matching TurboFilter found"); | |
super.start(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CustomTurboFilter extends TurboFilter { | |
private Map<String,Map<String,Level>> userCustomizationsMap = new HashMap<String, Map<String,Level>>(); | |
private Set<String> customizedUsersSet; | |
public FilterReply decide(Marker marker, Logger logger, Level level, String format, Object[] params, Throwable throwable) { | |
if (!isStarted()) | |
return FilterReply.NEUTRAL; | |
String user = MDC.get("userId"); | |
if (user == null) | |
return FilterReply.NEUTRAL; | |
Map<String, Level> map = userCustomizationsMap.get(user); | |
if (map == null) | |
return FilterReply.NEUTRAL; //undefined user | |
//test each logger-level for this user, find the closest match to 'logger' | |
String loggerName = logger.getName(); | |
Level specificLoggerLevel = null; | |
int specificLoggerNameLength = -1; | |
for (Entry<String, Level> e : map.entrySet()) { | |
String name = e.getKey(); | |
//FIXME This is awful code, I know, but I found no other way to check logger hierarchy (and LoggerComparator is not fit for this) | |
//FIXME guess it could be a bit faster using only 'startsWith', 'length' and 'charAt', but still String manipulation | |
if (loggerName.equals(name)) { | |
specificLoggerLevel = e.getValue(); //exact logger match | |
break; | |
} | |
//FIXME Here I attempt to find the most specific logger definition for the current logger (awful too) | |
int length = name.length(); | |
if (loggerName.startsWith(name+".") && length > specificLoggerNameLength) { | |
//the logger in this definition is a parent of 'logger', and longer name than the last one | |
specificLoggerNameLength = length; | |
specificLoggerLevel = e.getValue(); | |
} | |
} | |
if (specificLoggerLevel != null && level.isGreaterOrEqual(specificLoggerLevel)) { | |
return FilterReply.ACCEPT; //match found, force accept | |
} else { | |
return FilterReply.NEUTRAL; //no matching logger found, ignore | |
} | |
} | |
public void addUserCustomization(UserLoggersMapping userLoggersMapping) { | |
String user = userLoggersMapping.getUser(); | |
user = (user == null ? "" : user.trim()); | |
if (!user.isEmpty() && !userCustomizationsMap.containsKey(user)) { | |
Map<String,Level> loggerLevelMap = new HashMap<String, Level>(); | |
for (LoggerLevelPair llp : userLoggersMapping.getLoggerLevelList()) { | |
String logger = llp.getLogger(); | |
logger = (logger == null ? "" : logger.trim()); | |
if (!logger.isEmpty() && !loggerLevelMap.containsKey(logger) && llp.getLevel() != null) { | |
addInfo("Logger["+logger+"] level customized to "+llp.getLevel()+" for user "+user); | |
loggerLevelMap.put(logger, llp.getLevel()); | |
} | |
} | |
if (!loggerLevelMap.isEmpty()) { | |
userCustomizationsMap.put(user, loggerLevelMap); | |
} | |
} | |
} | |
public Set<String> getCustomizedUsersSet() { | |
return customizedUsersSet; | |
} | |
public void start() { | |
customizedUsersSet = Collections.unmodifiableSet(userCustomizationsMap.keySet()); //Will be used by CustomFilter | |
super.start(); | |
} | |
//Just JavaBeans, also shortening the code :-P | |
public static class UserLoggersMapping { | |
private String user; | |
private List<LoggerLevelPair> loggerLevelList = new ArrayList<LoggerLevelPair>(); | |
private String getUser() {return user;} | |
public void setUser(String user) {this.user = user;} | |
private List<LoggerLevelPair> getLoggerLevelList() {return loggerLevelList;} | |
public void addLoggerLevel(LoggerLevelPair levelLoggerPair) {loggerLevelList.add(levelLoggerPair);} | |
} | |
public static class LoggerLevelPair { | |
private Level level; | |
private String logger; | |
private Level getLevel() {return level;} | |
public void setLevel(Level level) {this.level = level;} | |
private String getLogger() {return logger;} | |
public void setLogger(String logger) {this.logger = logger;} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<configuration debug="true"> | |
<turboFilter class="com.sample.project.CustomTurboFilter"> | |
<userCustomization> | |
<user>ID_USER_1</user> | |
<loggerLevel> | |
<logger>com.sample.project</logger> | |
<level>DEBUG</level> | |
</loggerLevel> | |
<loggerLevel> | |
<logger>com.sample.legacy</logger> | |
<level>INFO</level> | |
</loggerLevel> | |
</userCustomization> | |
<userCustomization> | |
<user>ID_USER_2</user> | |
<loggerLevel> | |
<logger>com.sample.project</logger> | |
<level>TRACE</level> | |
</loggerLevel> | |
... | |
</userCustomization> | |
</turboFilter> | |
<appender name="FILTERED" class="ch.qos.logback.classic.sift.SiftingAppender"> | |
<discriminator class="ch.qos.logback.classic.sift.MDCBasedDiscriminator"> | |
<key>userId</key> | |
<defaultValue>unknown</defaultValue> | |
</discriminator> | |
<filter class="com.sample.project.CustomFilter"/> | |
<sift> ... </sift> | |
</appender> | |
<logger name="com.sample.project" level="WARN"> | |
<appender-ref ref="FILTERED" /> | |
</logger> | |
<root level="WARN"> | |
<appender-ref ref="STANDARD" /> | |
</root> | |
</configuration> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment