Moved general purpose stuff into util, renamed utils->util
This commit is contained in:
@@ -0,0 +1,380 @@
|
||||
package mightypork.util.logging;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import mightypork.util.annotations.FactoryMethod;
|
||||
import mightypork.util.logging.monitors.LogMonitor;
|
||||
import mightypork.util.logging.monitors.LogToSysoutMonitor;
|
||||
import mightypork.util.logging.writers.ArchivingLog;
|
||||
import mightypork.util.logging.writers.LogWriter;
|
||||
import mightypork.util.logging.writers.SimpleLog;
|
||||
import mightypork.util.string.StringUtils;
|
||||
|
||||
|
||||
/**
|
||||
* A log.
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class Log {
|
||||
|
||||
private static LogWriter main = null;
|
||||
private static boolean enabled = true;
|
||||
private static final LogToSysoutMonitor sysoMonitor = new LogToSysoutMonitor();
|
||||
private static final long start_ms = System.currentTimeMillis();
|
||||
|
||||
private static HashMap<String, SimpleLog> logs = new HashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* Create a logger. If another with the name already exists, it'll be
|
||||
* retrieved instead of creating a new one.
|
||||
*
|
||||
* @param logName log name (used for filename, should be application-unique)
|
||||
* @param logFile log file; old logs will be kept here too.
|
||||
* @param oldLogsCount number of old logs to keep, -1 infinite, 0 none.
|
||||
* @return the created Log instance
|
||||
*/
|
||||
@FactoryMethod
|
||||
public static synchronized LogWriter create(String logName, File logFile, int oldLogsCount)
|
||||
{
|
||||
if (logs.containsKey(logName)) return logs.get(logName);
|
||||
|
||||
final ArchivingLog log = new ArchivingLog(logName, logFile, oldLogsCount);
|
||||
log.init();
|
||||
|
||||
logs.put(logName, log);
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a logger. If another with the name already exists, it'll be
|
||||
* retrieved instead of creating a new one.
|
||||
*
|
||||
* @param logName log name (used for filename, must be application-unique)
|
||||
* @param logFile log file; old logs will be kept here too.
|
||||
* @return the created Log instance
|
||||
*/
|
||||
@FactoryMethod
|
||||
public static synchronized LogWriter create(String logName, File logFile)
|
||||
{
|
||||
if (logs.containsKey(logName)) return logs.get(logName);
|
||||
|
||||
final SimpleLog log = new SimpleLog(logName, logFile);
|
||||
log.init();
|
||||
|
||||
logs.put(logName, log);
|
||||
|
||||
return log;
|
||||
}
|
||||
|
||||
|
||||
public static void setMainLogger(LogWriter log)
|
||||
{
|
||||
main = log;
|
||||
}
|
||||
|
||||
|
||||
public static void addMonitor(LogMonitor mon)
|
||||
{
|
||||
assertInited();
|
||||
|
||||
main.addMonitor(mon);
|
||||
}
|
||||
|
||||
|
||||
public static void removeMonitor(LogMonitor mon)
|
||||
{
|
||||
assertInited();
|
||||
|
||||
main.removeMonitor(mon);
|
||||
}
|
||||
|
||||
|
||||
private static void assertInited()
|
||||
{
|
||||
if (main == null) throw new IllegalStateException("Main logger not initialized.");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log a message
|
||||
*
|
||||
* @param level message level
|
||||
* @param msg message text
|
||||
*/
|
||||
public static void log(Level level, String msg)
|
||||
{
|
||||
if (enabled) {
|
||||
sysoMonitor.onMessageLogged(level, formatMessage(level, msg, null, start_ms));
|
||||
|
||||
if (main != null) {
|
||||
main.log(level, msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log a message
|
||||
*
|
||||
* @param level message level
|
||||
* @param msg message text
|
||||
* @param t thrown exception
|
||||
*/
|
||||
public static void log(Level level, String msg, Throwable t)
|
||||
{
|
||||
if (enabled) {
|
||||
sysoMonitor.onMessageLogged(level, formatMessage(level, msg, t, start_ms));
|
||||
|
||||
if (main != null) {
|
||||
main.log(level, msg, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log FINE message
|
||||
*
|
||||
* @param msg message
|
||||
*/
|
||||
public static void f1(String msg)
|
||||
{
|
||||
log(Level.FINE, msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log FINER message
|
||||
*
|
||||
* @param msg message
|
||||
*/
|
||||
public static void f2(String msg)
|
||||
{
|
||||
log(Level.FINER, msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log FINEST message
|
||||
*
|
||||
* @param msg message
|
||||
*/
|
||||
public static void f3(String msg)
|
||||
{
|
||||
log(Level.FINEST, msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log INFO message
|
||||
*
|
||||
* @param msg message
|
||||
*/
|
||||
public static void i(String msg)
|
||||
{
|
||||
log(Level.INFO, msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log WARNING message (less severe than ERROR)
|
||||
*
|
||||
* @param msg message
|
||||
*/
|
||||
public static void w(String msg)
|
||||
{
|
||||
log(Level.WARNING, msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log ERROR message
|
||||
*
|
||||
* @param msg message
|
||||
*/
|
||||
public static void e(String msg)
|
||||
{
|
||||
log(Level.SEVERE, msg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log warning message with exception
|
||||
*
|
||||
* @param msg message
|
||||
* @param thrown thrown exception
|
||||
*/
|
||||
public static void w(String msg, Throwable thrown)
|
||||
{
|
||||
log(Level.WARNING, msg, thrown);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log exception thrown as warning
|
||||
*
|
||||
* @param thrown thrown exception
|
||||
*/
|
||||
public static void w(Throwable thrown)
|
||||
{
|
||||
log(Level.WARNING, null, thrown);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log error message
|
||||
*
|
||||
* @param msg message
|
||||
* @param thrown thrown exception
|
||||
*/
|
||||
public static void e(String msg, Throwable thrown)
|
||||
{
|
||||
log(Level.SEVERE, msg, thrown);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log exception thrown as error
|
||||
*
|
||||
* @param thrown thrown exception
|
||||
*/
|
||||
public static void e(Throwable thrown)
|
||||
{
|
||||
log(Level.SEVERE, null, thrown);
|
||||
}
|
||||
|
||||
|
||||
public static void enable(boolean flag)
|
||||
{
|
||||
enabled = flag;
|
||||
}
|
||||
|
||||
|
||||
public static void setSysoutLevel(Level level)
|
||||
{
|
||||
sysoMonitor.setLevel(level);
|
||||
}
|
||||
|
||||
|
||||
public static void setLevel(Level level)
|
||||
{
|
||||
assertInited();
|
||||
|
||||
main.setLevel(level);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get stack trace from throwable
|
||||
*
|
||||
* @param t
|
||||
* @return trace
|
||||
*/
|
||||
public static String getStackTrace(Throwable t)
|
||||
{
|
||||
final StringWriter sw = new StringWriter();
|
||||
final PrintWriter pw = new PrintWriter(sw, true);
|
||||
t.printStackTrace(pw);
|
||||
pw.flush();
|
||||
sw.flush();
|
||||
return sw.toString();
|
||||
}
|
||||
|
||||
|
||||
public static String formatMessage(Level level, String message, Throwable throwable, long start_ms)
|
||||
{
|
||||
|
||||
final String nl = System.getProperty("line.separator");
|
||||
|
||||
if (message.equals("\n")) {
|
||||
return nl;
|
||||
}
|
||||
|
||||
if (message.charAt(0) == '\n') {
|
||||
message = nl + message.substring(1);
|
||||
}
|
||||
|
||||
final long time_ms = (System.currentTimeMillis() - start_ms);
|
||||
final double time_s = time_ms / 1000D;
|
||||
final String time = String.format("%6.2f ", time_s);
|
||||
final String time_blank = StringUtils.repeat(" ", time.length());
|
||||
|
||||
String prefix = "[ ? ]";
|
||||
|
||||
if (level == Level.FINE) {
|
||||
prefix = "[ # ] ";
|
||||
} else if (level == Level.FINER) {
|
||||
prefix = "[ - ] ";
|
||||
} else if (level == Level.FINEST) {
|
||||
prefix = "[ ] ";
|
||||
} else if (level == Level.INFO) {
|
||||
prefix = "[ i ] ";
|
||||
} else if (level == Level.SEVERE) {
|
||||
prefix = "[!E!] ";
|
||||
} else if (level == Level.WARNING) {
|
||||
prefix = "[!W!] ";
|
||||
}
|
||||
|
||||
message = time + prefix + message.replaceAll("\n", nl + time_blank + prefix) + nl;
|
||||
|
||||
if (throwable != null) {
|
||||
message += getStackTrace(throwable);
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
public static String str(Object o)
|
||||
{
|
||||
|
||||
boolean hasToString = false;
|
||||
|
||||
try {
|
||||
hasToString = (o.getClass().getMethod("toString").getDeclaringClass() != Object.class);
|
||||
} catch (final Exception e) {
|
||||
// oh well..
|
||||
}
|
||||
|
||||
if (hasToString) {
|
||||
return o.toString();
|
||||
} else {
|
||||
|
||||
return str(o.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String str(Class<?> cls)
|
||||
{
|
||||
final LogAlias ln = cls.getAnnotation(LogAlias.class);
|
||||
if (ln != null) {
|
||||
return ln.name();
|
||||
}
|
||||
|
||||
String name = cls.getName();
|
||||
|
||||
String sep = "";
|
||||
|
||||
if (name.contains("$")) {
|
||||
name = name.substring(name.lastIndexOf("$") + 1);
|
||||
sep = "$";
|
||||
} else {
|
||||
name = name.substring(name.lastIndexOf(".") + 1);
|
||||
sep = ".";
|
||||
}
|
||||
|
||||
final Class<?> enclosing = cls.getEnclosingClass();
|
||||
|
||||
return (enclosing == null ? "" : str(enclosing) + sep) + name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package mightypork.util.logging;
|
||||
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
|
||||
/**
|
||||
* Specify pretty name to be used when logging (eg. <code>Log.str()</code>)
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
public @interface LogAlias {
|
||||
|
||||
String name();
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package mightypork.util.logging.monitors;
|
||||
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
||||
public abstract class BaseLogMonitor implements LogMonitor {
|
||||
|
||||
private boolean enabled = true;
|
||||
private Level accepted = Level.ALL;
|
||||
|
||||
|
||||
@Override
|
||||
public void onMessageLogged(Level level, String message)
|
||||
{
|
||||
if (!enabled) return;
|
||||
if (accepted.intValue() > level.intValue()) return;
|
||||
|
||||
logMessage(level, message);
|
||||
}
|
||||
|
||||
|
||||
protected abstract void logMessage(Level level, String message);
|
||||
|
||||
|
||||
@Override
|
||||
public void setLevel(Level level)
|
||||
{
|
||||
this.accepted = level;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void enable(boolean flag)
|
||||
{
|
||||
this.enabled = flag;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package mightypork.util.logging.monitors;
|
||||
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
||||
public interface LogMonitor {
|
||||
|
||||
void onMessageLogged(Level level, String message);
|
||||
|
||||
|
||||
void setLevel(Level level);
|
||||
|
||||
|
||||
void enable(boolean flag);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package mightypork.util.logging.monitors;
|
||||
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
||||
public class LogToSysoutMonitor extends BaseLogMonitor {
|
||||
|
||||
@Override
|
||||
protected void logMessage(Level level, String message)
|
||||
{
|
||||
if (level == Level.SEVERE || level == Level.WARNING) {
|
||||
System.err.print(message);
|
||||
} else {
|
||||
System.out.print(message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package mightypork.util.logging.writers;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import mightypork.util.files.FileUtils;
|
||||
|
||||
|
||||
/**
|
||||
* Logger that cleans directory & archives old logs
|
||||
*
|
||||
* @author MightyPork
|
||||
* @copy (c) 2014
|
||||
*/
|
||||
public class ArchivingLog extends SimpleLog {
|
||||
|
||||
/** Number of old logs to keep */
|
||||
private final int logs_to_keep;
|
||||
|
||||
|
||||
/**
|
||||
* Log
|
||||
*
|
||||
* @param name log name
|
||||
* @param file log file (in log directory)
|
||||
* @param oldLogCount number of old log files to keep: -1 all, 0 none.
|
||||
*/
|
||||
public ArchivingLog(String name, File file, int oldLogCount) {
|
||||
super(name, file);
|
||||
this.logs_to_keep = oldLogCount;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Log, not keeping 5 last log files (default);
|
||||
*
|
||||
* @param name log name
|
||||
* @param file log file (in log directory)
|
||||
*/
|
||||
public ArchivingLog(String name, File file) {
|
||||
super(name, file);
|
||||
this.logs_to_keep = 5;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
cleanLoggingDirectory();
|
||||
|
||||
super.init();
|
||||
}
|
||||
|
||||
|
||||
private void cleanLoggingDirectory()
|
||||
{
|
||||
if (logs_to_keep == 0) return; // overwrite
|
||||
|
||||
final File log_file = getFile();
|
||||
final File log_dir = log_file.getParentFile();
|
||||
final String fname = FileUtils.getBasename(log_file.toString());
|
||||
|
||||
// move old file
|
||||
for (final File f : FileUtils.listDirectory(log_dir)) {
|
||||
if (!f.isFile()) continue;
|
||||
if (f.equals(getFile())) {
|
||||
|
||||
final Date d = new Date(f.lastModified());
|
||||
final String fbase = fname + '_' + (new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss")).format(d);
|
||||
final String suff = "." + getSuffix();
|
||||
String cntStr = "";
|
||||
File f2;
|
||||
|
||||
for (int cnt = 0; (f2 = new File(log_dir, fbase + cntStr + suff)).exists(); cntStr = "_" + (++cnt)) {}
|
||||
|
||||
if (!f.renameTo(f2)) throw new RuntimeException("Could not move log file.");
|
||||
}
|
||||
}
|
||||
|
||||
if (logs_to_keep == -1) return; // keep all
|
||||
|
||||
final List<File> oldLogs = FileUtils.listDirectory(log_dir, new FileFilter() {
|
||||
|
||||
@Override
|
||||
public boolean accept(File f)
|
||||
{
|
||||
if (f.isDirectory()) return false;
|
||||
if (!f.getName().endsWith(getSuffix())) return false;
|
||||
if (!f.getName().startsWith(fname)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Collections.sort(oldLogs, new Comparator<File>() {
|
||||
|
||||
@Override
|
||||
public int compare(File o1, File o2)
|
||||
{
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
});
|
||||
|
||||
// playing with fireee
|
||||
for (int i = 0; i < oldLogs.size() - logs_to_keep; i++) {
|
||||
if (!oldLogs.get(i).delete()) {
|
||||
throw new RuntimeException("Could not delete old log file.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return log filename suffix
|
||||
*/
|
||||
private String getSuffix()
|
||||
{
|
||||
return FileUtils.getExtension(getFile());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package mightypork.util.logging.writers;
|
||||
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
import mightypork.util.logging.monitors.LogMonitor;
|
||||
|
||||
|
||||
/**
|
||||
* Log interface
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public interface LogWriter {
|
||||
|
||||
/**
|
||||
* Prepare logs for logging
|
||||
*/
|
||||
void init();
|
||||
|
||||
|
||||
/**
|
||||
* Add log monitor
|
||||
*
|
||||
* @param mon monitor
|
||||
*/
|
||||
void addMonitor(LogMonitor mon);
|
||||
|
||||
|
||||
/**
|
||||
* Remove a monitor
|
||||
*
|
||||
* @param removed monitor to remove
|
||||
*/
|
||||
void removeMonitor(LogMonitor removed);
|
||||
|
||||
|
||||
/**
|
||||
* Set logging level
|
||||
*
|
||||
* @param level
|
||||
*/
|
||||
void setLevel(Level level);
|
||||
|
||||
|
||||
/**
|
||||
* Enable logging.
|
||||
*
|
||||
* @param flag do enable logging
|
||||
*/
|
||||
void enable(boolean flag);
|
||||
|
||||
|
||||
/**
|
||||
* Log a message
|
||||
*
|
||||
* @param level message level
|
||||
* @param msg message text
|
||||
*/
|
||||
void log(Level level, String msg);
|
||||
|
||||
|
||||
/**
|
||||
* Log a message
|
||||
*
|
||||
* @param level message level
|
||||
* @param msg message text
|
||||
* @param t thrown exception
|
||||
*/
|
||||
void log(Level level, String msg, Throwable t);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
package mightypork.util.logging.writers;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import mightypork.util.logging.Log;
|
||||
import mightypork.util.logging.monitors.LogMonitor;
|
||||
|
||||
|
||||
/**
|
||||
* Basic logger
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class SimpleLog implements LogWriter {
|
||||
|
||||
/**
|
||||
* Log file formatter.
|
||||
*/
|
||||
class LogFormatter extends Formatter {
|
||||
|
||||
@Override
|
||||
public String format(LogRecord record)
|
||||
{
|
||||
return Log.formatMessage(record.getLevel(), record.getMessage(), record.getThrown(), started_ms);
|
||||
}
|
||||
}
|
||||
|
||||
/** Log file */
|
||||
private final File file;
|
||||
|
||||
/** Log name */
|
||||
private final String name;
|
||||
|
||||
/** Logger instance. */
|
||||
private Logger logger;
|
||||
|
||||
private boolean enabled = true;
|
||||
private final HashSet<LogMonitor> monitors = new HashSet<>();
|
||||
private final long started_ms;
|
||||
|
||||
|
||||
public SimpleLog(String name, File file) {
|
||||
this.name = name;
|
||||
this.file = file;
|
||||
this.started_ms = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
logger = Logger.getLogger(getName());
|
||||
|
||||
FileHandler handler = null;
|
||||
try {
|
||||
handler = new FileHandler(getFile().getPath());
|
||||
} catch (final Exception e) {
|
||||
throw new RuntimeException("Failed to init log.", e);
|
||||
}
|
||||
|
||||
handler.setFormatter(new LogFormatter());
|
||||
logger.addHandler(handler);
|
||||
logger.setUseParentHandlers(false);
|
||||
logger.setLevel(Level.ALL);
|
||||
|
||||
printHeader();
|
||||
}
|
||||
|
||||
|
||||
protected void printHeader()
|
||||
{
|
||||
final String stamp = (new SimpleDateFormat("yyyy/MM/dd HH:mm:ss")).format(new Date());
|
||||
log(Level.INFO, "Logger \"" + getName() + "\" initialized.\n" + stamp);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add log monitor
|
||||
*
|
||||
* @param mon monitor
|
||||
*/
|
||||
@Override
|
||||
public synchronized void addMonitor(LogMonitor mon)
|
||||
{
|
||||
monitors.add(mon);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove a monitor
|
||||
*
|
||||
* @param removed monitor to remove
|
||||
*/
|
||||
@Override
|
||||
public synchronized void removeMonitor(LogMonitor removed)
|
||||
{
|
||||
monitors.remove(removed);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void setLevel(Level level)
|
||||
{
|
||||
logger.setLevel(level);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void enable(boolean flag)
|
||||
{
|
||||
enabled = flag;
|
||||
}
|
||||
|
||||
|
||||
public File getFile()
|
||||
{
|
||||
return file;
|
||||
}
|
||||
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void log(Level level, String msg)
|
||||
{
|
||||
if (enabled) {
|
||||
logger.log(level, msg);
|
||||
|
||||
final String fmt = Log.formatMessage(level, msg, null, started_ms);
|
||||
|
||||
for (final LogMonitor mon : monitors) {
|
||||
mon.onMessageLogged(level, fmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void log(Level level, String msg, Throwable t)
|
||||
{
|
||||
if (enabled) {
|
||||
logger.log(level, msg, t);
|
||||
|
||||
final String fmt = Log.formatMessage(level, msg, t, started_ms);
|
||||
|
||||
for (final LogMonitor mon : monitors) {
|
||||
mon.onMessageLogged(level, fmt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user