Skip to content

Instantly share code, notes, and snippets.

@JensMeiners
Last active March 3, 2016 06:40
Show Gist options
  • Save JensMeiners/b880c716edd4eaf3c027 to your computer and use it in GitHub Desktop.
Save JensMeiners/b880c716edd4eaf3c027 to your computer and use it in GitHub Desktop.
Evaluation Logger for log4j 1.7.10
2016-03-02 09:06:53,216|EvalLevelTest|main|18|Eval log
package de.dailab.newsreel.recommender.common.util;
import org.apache.log4j.Level;
/**
* This program is free software. It comes without any warranty, to
* the extent permitted by applicable law. You can redistribute it
* and/or modify it under the terms of the Do What The Fuck You Want
* To Public License, Version 2, as published by Sam Hocevar. See
* http://www.wtfpl.net/ for more details.
*/
public class EvalLevel extends Level {
/**
* This Level is lower than all normal levels, therefor it will not appear in any other loggers
*/
public static final int EVAL_INT = 1;
private static final String NAME = "EVAL";
/**
* Level representing my log level
*/
public static final Level EVAL = new EvalLevel(EVAL_INT, NAME, 10);
/**
* Instantiate a Level object.
*
* @param level
* @param levelStr
* @param syslogEquivalent
*/
protected EvalLevel(int level, String levelStr, int syslogEquivalent) {
super(level, levelStr, syslogEquivalent);
}
/**
* Checks whether logArgument is "EVAL" level. If yes then returns
* EVAL}, else calls EvalLevel#toLevel(String, Level) passing
* it Level#DEBUG as the defaultLevel.
*/
public static Level toLevel(String logArgument) {
if (logArgument != null && logArgument.toUpperCase().equals(NAME)) {
return EVAL;
}
return (Level) toLevel(logArgument);
}
/**
* Checks whether val is EvalLevel#EVAL_INT. If yes then
* returns EvalLevel#EVAL, else calls
* EvalLevel#toLevel(int, Level) passing it Level#DEBUG as the
* defaultLevel
*
*/
public static Level toLevel(int val) {
if (val == EVAL_INT) {
return EVAL;
}
return (Level) toLevel(val, Level.DEBUG);
}
/**
* Checks whether val is EvalLevel#EVAL_INT. If yes
* then returns EvalLevel#EVAL, else calls Level#toLevel(int, org.apache.log4j.Level)
*
*/
public static Level toLevel(int val, Level defaultLevel) {
if (val == EVAL_INT) {
return EVAL;
}
return Level.toLevel(val, defaultLevel);
}
/**
* Checks whether logArgument is "EVAL" level. If yes then returns
* EvalLevel#EVAL, else calls
* Level#toLevel(java.lang.String, org.apache.log4j.Level)
*
*/
public static Level toLevel(String logArgument, Level defaultLevel) {
if (logArgument != null && logArgument.toUpperCase().equals(NAME)) {
return EVAL;
}
return Level.toLevel(logArgument, defaultLevel);
}
}
package de.dailab.newsreel.recommender.common.util;
import org.apache.commons.lang.NullArgumentException;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
/**
* Created by jens on 02.03.16.
*/
public class EvalLevelTest {
public static void main(String[] args) {
Logger logger = Logger.getLogger(EvalLevel.class);
logger.setLevel(EvalLevel.EVAL);
Throwable _throw = new NullArgumentException("some npe");
logger.log(EvalLevel.EVAL, "Eval log", _throw);
logger.log(Level.DEBUG, "DEBUG message");
logger.log(Level.INFO, "INFO message");
}
}
log4j.rootLogger= eval
# Direct log messages to a log file
log4j.appender.eval=org.apache.log4j.RollingFileAppender
log4j.appender.eval.Threshold=EVAL#de.dailab.newsreel.recommender.common.util.EvalLevel
log4j.appender.eval.filter.a=org.apache.log4j.varia.LevelRangeFilter
log4j.appender.eval.filter.a.LevelMin=EVAL#de.dailab.newsreel.recommender.common.util.EvalLevel
log4j.appender.eval.filter.a.LevelMax=EVAL#de.dailab.newsreel.recommender.common.util.EvalLevel
log4j.appender.eval.File=eval.log
log4j.appender.eval.MaxFileSize=500MB
log4j.appender.eval.MaxBackupIndex=6
log4j.appender.eval.layout=org.apache.log4j.EnhancedPatternLayout
log4j.appender.eval.layout.ConversionPattern=%d{ISO8601}|%C{1}|%M|%L|%m%throwable{none}%n
@JensMeiners
Copy link
Author

This custom Log-Level will generate a file that contains EVAL-Level logs only and is easily readable using csv-readers. Note that comma was no possible choice as a separator because it is used for the ISO-DateFormat. Also, using another separator makes it possible to log any strings of user generated content without blowing up the file structure. On the other hand, carful usage of the new separator gives the possiblity to dynamically extend the mentioned structure.

Be careful however using throwables, these will be discarded. Another log-level seems more appropriate for that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment