All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.nomou.log4web.LogWatcher Maven / Gradle / Ivy

/*
 * Copyright (c) 2005, 2014 vacoor
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package com.github.nomou.log4web;

import com.github.nomou.log4web.cfg.ListenerConfig;
import com.github.nomou.log4web.cfg.LogWatcherConfig;
import com.github.nomou.log4web.history.CircularList;
import com.github.nomou.log4web.internal.jul.JulWatcher;
import com.github.nomou.log4web.internal.log4j.Log4jWatcher;
import com.github.nomou.log4web.internal.logback.LogbackWatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.impl.StaticLoggerBinder;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Log watcher.
 *
 * @param  the log event
 * @author vacoor
 */
public abstract class LogWatcher {

    /**
     * The time of log.
     */
    public static final String TIME_KEY = "time";

    /**
     * The level of log.
     */
    public static final String LEVEL_KEY = "level";

    /**
     * The logger name of log.
     */
    public static final String LOGGER_KEY = "logger";

    /**
     * The message of log.
     */
    public static final String MESSAGE_KEY = "message";

    /**
     * The stack trace of log.
     */
    public static final String TRACE_KEY = "trace";

    /**
     * Logger.
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(LogWatcher.class);

    /**
     * SLF4j-log4j factory.
     */
    private static final String LOG4J_LOGGER_FACTORY = "org.slf4j.impl.Log4jLoggerFactory";

    /**
     * SLF4j-logback-classic factory.
     */
    private static final String LOGBACK_CLASSIC_LOGGER_FACTORY = "ch.qos.logback.classic.util.ContextSelectorStaticBinder";


    /**
     * The history list for log.
     */
    private CircularList history;

    /**
     * The last time for log.
     */
    private long last = -1L;

    /**
     * Gets the watcher name.
     *
     * @return the watcher name
     */
    public abstract String getName();

    /**
     * Gets the watcher threshold level.
     *
     * @return the watcher threshold level
     */
    public abstract String getThreshold();

    /**
     * Sets the watcher threshold level.
     */
    public abstract void setThreshold(final String level);

    /**
     * Gets the all levels of log for the current log implementation.
     *
     * @return the levels of log
     */
    public abstract List getAllLevels();

    /**
     * Gets the configured loggers.
     *
     * @return the loggers info
     */
    public abstract Collection getAllLoggers();

    /**
     * Sets level for the given category.
     *
     * @param category the category for logger
     * @param level    the level of log
     */
    public abstract void setLogLevel(final String category, final String level);

    /**
     * Adds the log event to watcher.
     *
     * @param event  the log event
     * @param millis the happen time (ms)
     */
    public void add(final E event, final long millis) {
        this.history.add(event);
        this.last = millis;
    }

    /**
     * @return
     */
    public long getLastEvent() {
        return this.last;
    }

    public int getHistorySize() {
        return this.history == null ? -1 : this.history.getBufferSize();
    }

    public List> getHistory(final long since, final AtomicBoolean found) {
        final List> logs = new ArrayList>();
        if (this.history == null) {
            return logs;
        }

        for (final E event : this.history) {
            final long ts = getTimestamp(event);
            if ((ts == since) && (found != null)) {
                found.set(true);
            }

            if (ts > since) {
                logs.add(toInfoMap(event));
            }
        }
        return logs;
    }

    public abstract long getTimestamp(E event);

    public abstract Map toInfoMap(final E event);

    public void registerListener(final ListenerConfig cfg) {
        if (null != this.history) {
            throw new IllegalStateException("History already registered");
        }
        this.history = new CircularList(cfg.size);
        this.doRegisterListener(cfg);
    }

    protected abstract void doRegisterListener(final ListenerConfig listenerConfig);

    public void reset() {
        this.history.clear();
        this.last = -1L;
    }

    public abstract void close();

    public boolean isUnsetLevel(final String level) {
        return null == level || "null".equals(level) || "unset".equals(level);
    }

    public static LogWatcher newRegisteredLogWatcher(final LogWatcherConfig cfg) {
        if (!cfg.isEnabled()) {
            LOGGER.info("A LogWatcher is not enabled");
            return null;
        }

        final LogWatcher watcher = createWatcher(cfg);
        if ((null != watcher) && (cfg.getWatcherSize() > 0)) {
            LOGGER.info("Registering Log Listener [{}]", watcher.getName());

            watcher.registerListener(cfg.asListenerConfig());
        }

        return watcher;
    }

    private static LogWatcher createWatcher(LogWatcherConfig cfg) {
        String loggingClass = cfg.getLoggingClass();
        String slf4jImpl;
        try {
            slf4jImpl = StaticLoggerBinder.getSingleton().getLoggerFactoryClassStr();

            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("SLF4J impl is {}", slf4jImpl);
            }

            if (null == loggingClass) {
                if (LOG4J_LOGGER_FACTORY.equals(slf4jImpl)) {
                    loggingClass = "Log4j";
                } else if (LOGBACK_CLASSIC_LOGGER_FACTORY.equals(slf4jImpl)) {
                    loggingClass = "Logback-classic";
                } else if (slf4jImpl.indexOf("JDK") > 0) {
                    loggingClass = "JUL";
                }
            }
        } catch (Throwable e) {
            LOGGER.warn("Unable to read SLF4J version.  LogWatcher will be disabled: " + e);

            if ((e instanceof OutOfMemoryError)) {
                throw ((OutOfMemoryError) e);
            }
            return null;
        }

        if (null == loggingClass) {
            LOGGER.info("No LogWatcher configured");
            return null;
        }

        if ("JUL".equalsIgnoreCase(loggingClass)) {
            return new JulWatcher(slf4jImpl);
        }
        if ("Log4j".equals(loggingClass)) {
            return new Log4jWatcher(slf4jImpl);
        }
        if ("Logback-classic".equals(loggingClass)) {
            return new LogbackWatcher(slf4jImpl);
        }

        final ClassLoader loader = LogWatcher.class.getClassLoader();
        try {
            final Class clazz = Class.forName(loggingClass, true, loader);
            if (!LogWatcher.class.isAssignableFrom(clazz)) {
                throw new IllegalStateException('\'' + loggingClass + "' is not a LogWatcher");
            }

            Object instance = null;
            Constructor ctor = findConstructor(clazz);
            if (null != ctor) {
                instance = ctor.newInstance();
            } else {
                ctor = findConstructor(clazz, String.class);
                instance = null != ctor ? ctor.newInstance(slf4jImpl) : null;
            }

            if (null == ctor) {
                throw new IllegalStateException("can not instantiation: " + loggingClass);
            }

            return (LogWatcher) instance;
        } catch (final ClassNotFoundException e) {
            LOGGER.warn("Unable to load LogWatcher {}: {}", loggingClass, e);
            throw new UndeclaredThrowableException(e);
        } catch (final IllegalAccessException e) {
            LOGGER.warn("Unable to load LogWatcher {}: {}", loggingClass, e);
            throw new UndeclaredThrowableException(e);
        } catch (final InstantiationException e) {
            LOGGER.warn("Unable to load LogWatcher {}: {}", loggingClass, e);
            throw new UndeclaredThrowableException(e);
        } catch (final InvocationTargetException e) {
            LOGGER.warn("Unable to load LogWatcher {}: {}", loggingClass, e);
            throw new UndeclaredThrowableException(e);
        }
    }

    private static  Constructor findConstructor(final Class target, final Class... parameterTypes) {
        try {
            return target.getConstructor(parameterTypes);
        } catch (final NoSuchMethodException e) {
            return null;
        }
    }

    /**
     * Gets the throwable stack trace as string.
     *
     * @param t the throwable
     * @return the stack trace string
     */
    protected static String getStackTraceAsString(final Throwable t) {
        final StringWriter writer = new StringWriter();
        t.printStackTrace(new PrintWriter(writer));
        return writer.toString();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy