/* * Copyright 2012 - 2016 Anton Tananaev (anton@traccar.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.traccar.helper; import org.apache.log4j.Appender; import org.apache.log4j.DailyRollingFileAppender; import org.apache.log4j.Layout; import org.apache.log4j.Level; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.varia.NullAppender; import org.jboss.netty.logging.AbstractInternalLogger; import org.jboss.netty.logging.InternalLogger; import org.jboss.netty.logging.InternalLoggerFactory; import org.traccar.Config; import java.io.IOException; import java.lang.management.ManagementFactory; import java.lang.management.MemoryMXBean; import java.lang.management.OperatingSystemMXBean; import java.lang.management.RuntimeMXBean; import java.nio.charset.Charset; public final class Log { private Log() { } public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; private static final String LOGGER_NAME = "traccar"; private static final String STACK_PACKAGE = "org.traccar"; private static final int STACK_LIMIT = 3; private static Logger logger = null; public static String getAppVersion() { return Log.class.getPackage().getImplementationVersion(); } public static void setupLogger(Config config) throws IOException { Layout layout = new PatternLayout("%d{" + DATE_FORMAT + "} %5p: %m%n"); Appender appender = new DailyRollingFileAppender( layout, config.getString("logger.file"), "'.'yyyyMMdd"); LogManager.resetConfiguration(); LogManager.getRootLogger().addAppender(new NullAppender()); logger = Logger.getLogger(LOGGER_NAME); logger.addAppender(appender); logger.setLevel(Level.toLevel(config.getString("logger.level"), Level.ALL)); // Workaround for "Bug 745866 - (EDG-45) Possible netty logging config problem" InternalLoggerFactory.setDefaultFactory(new InternalLoggerFactory() { @Override public InternalLogger newInstance(String string) { return new NettyInternalLogger(); } }); Log.logSystemInfo(); Log.info("Version: " + getAppVersion()); } public static Logger getLogger() { if (logger == null) { logger = Logger.getLogger(LOGGER_NAME); logger.setLevel(Level.OFF); } return logger; } public static void logSystemInfo() { try { OperatingSystemMXBean operatingSystemBean = ManagementFactory.getOperatingSystemMXBean(); Log.info("Operating system" + " name: " + operatingSystemBean.getName() + " version: " + operatingSystemBean.getVersion() + " architecture: " + operatingSystemBean.getArch()); RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); Log.info("Java runtime" + " name: " + runtimeBean.getVmName() + " vendor: " + runtimeBean.getVmVendor() + " version: " + runtimeBean.getVmVersion()); MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean(); Log.info("Memory limit" + " heap: " + memoryBean.getHeapMemoryUsage().getMax() / (1024 * 1024) + "mb" + " non-heap: " + memoryBean.getNonHeapMemoryUsage().getMax() / (1024 * 1024) + "mb"); Log.info("Character encoding: " + System.getProperty("file.encoding") + " charset: " + Charset.defaultCharset()); } catch (Exception error) { Log.warning("Failed to get system info"); } } public static void error(String msg) { getLogger().error(msg); } public static void warning(String msg) { getLogger().warn(msg); } public static void warning(Throwable exception) { warning(null, exception); } public static void warning(String msg, Throwable exception) { StringBuilder s = new StringBuilder(); if (msg != null) { s.append(msg); } if (exception != null) { if (msg != null) { s.append(" - "); } s.append(exceptionStack(exception)); } getLogger().warn(s.toString()); } public static void info(String msg) { getLogger().info(msg); } public static void debug(String msg) { getLogger().debug(msg); } public static String exceptionStack(Throwable exception) { StringBuilder s = new StringBuilder(); String exceptionMsg = exception.getMessage(); if (exceptionMsg != null) { s.append(exceptionMsg); s.append(" - "); } s.append(exception.getClass().getSimpleName()); StackTraceElement[] stack = exception.getStackTrace(); if (stack.length > 0) { int count = STACK_LIMIT; boolean first = true; boolean skip = false; String file = ""; s.append(" ("); for (StackTraceElement element : stack) { if (count > 0 && element.getClassName().startsWith(STACK_PACKAGE)) { if (!first) { s.append(" < "); } else { first = false; } if (skip) { s.append("... < "); skip = false; } if (file.equals(element.getFileName())) { s.append("*"); } else { file = element.getFileName(); s.append(file.substring(0, file.length() - 5)); // remove ".java" count -= 1; } s.append(":").append(element.getLineNumber()); } else { skip = true; } } if (skip) { if (!first) { s.append(" < "); } s.append("..."); } s.append(")"); } return s.toString(); } /** * Netty logger implementation */ private static class NettyInternalLogger extends AbstractInternalLogger { @Override public boolean isDebugEnabled() { return false; } @Override public boolean isInfoEnabled() { return false; } @Override public boolean isWarnEnabled() { return true; } @Override public boolean isErrorEnabled() { return true; } @Override public void debug(String string) { debug(string, null); } @Override public void debug(String string, Throwable thrwbl) { } @Override public void info(String string) { info(string, null); } @Override public void info(String string, Throwable thrwbl) { } @Override public void warn(String string) { warn(string, null); } @Override public void warn(String string, Throwable thrwbl) { getLogger().warn("netty warning: " + string); } @Override public void error(String string) { error(string, null); } @Override public void error(String string, Throwable thrwbl) { getLogger().error("netty error: " + string); } } }