Skip to content

Instantly share code, notes, and snippets.

Created December 20, 2011 16:03
Show Gist options
  • Save anonymous/1502077 to your computer and use it in GitHub Desktop.
Save anonymous/1502077 to your computer and use it in GitHub Desktop.
Logback files
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();
}
}
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;}
}
}
<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