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

com.cinchapi.common.logging.Logger Maven / Gradle / Ivy

Go to download

Accent4J is a suite of libraries, helpers and data structures that make Java programming idioms more fluent.

There is a newer version: 1.13.1
Show newest version
/*
 * Copyright (c) 2016 Cinchapi Inc.
 * 
 * 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 com.cinchapi.common.logging;

import java.io.File;
import java.util.UUID;

import javax.annotation.concurrent.Immutable;

import org.slf4j.LoggerFactory;

import com.cinchapi.common.io.Files;
import com.google.common.base.Preconditions;

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy;

/**
 * A programmatically configurable logging facade.
 * 
 * @author Jeff Nelson
 */
@Immutable
public final class Logger {

    /**
     * Return a builder for constructing a new {@link Logger} instance.
     * 
     * @return the builder
     */
    public static Builder builder() {
        return new Builder();
    }

    /**
     * Return a {@link Logger} that is configured to only log to the console
     * instead of a specific directory.
     * 
     * @param name the name of the Logger
     * @param level the log level
     * @return the configured Logger
     */
    public static Logger console(String name, Level level) {
        return builder().name(name).directory(Files.tempDir("logger"))
                .enableConsoleLogging(true).level(level).build();
    }

    /**
     * Return a {@link Logger} that is configured to only log to the console
     * instead of a specific directory.
     * 
     * @param name the name of the Logger
     * @return the configured Logger
     */
    public static Logger console(String name) {
        return console(name, Level.DEBUG);
    }

    /**
     * Return a {@link Logger} that doesn't log messages to anywhere.
     * 
     * @return the fake Logger
     */
    public static Logger none() {
        return builder().name("none")
                .directory(Files.tempDir(UUID.randomUUID().toString()))
                .enableConsoleLogging(false).level(Level.ERROR).build();
    }

    /**
     * The internal logger for the {@link #debug(String, Object...)} method.
     */
    private final ch.qos.logback.classic.Logger debug;

    /**
     * The directory where the log files are placed.
     */
    private final String directory;

    /**
     * A flag that indicates whether the Logger should log to the console.
     */
    private final boolean enableConsoleLogging;

    /**
     * The internal logger for the {@link #error(String, Object...)} method.
     */
    private final ch.qos.logback.classic.Logger error;

    /**
     * The internal logger for the {@link #info(String, Object...)} method.
     */
    private final ch.qos.logback.classic.Logger info;

    /**
     * The level at which the Logger is configured.
     */
    private final Level level;

    /**
     * The max file size of a log before its rolled over and archived.
     */
    private final String maxFileSize;

    /**
     * The internal logger for the {@link #warn(String, Object...)} method.
     */
    private final ch.qos.logback.classic.Logger warn;

    /**
     * Construct a new instance.
     * 
     * @param name
     * @param level
     * @param directory
     * @param maxFileSize
     */
    private Logger(String name, Level level, String directory,
            String maxFileSize, boolean enableConsoleLogging) {
        Preconditions.checkNotNull(name);
        Preconditions.checkNotNull(level);
        Preconditions.checkNotNull(directory);
        Preconditions.checkNotNull(maxFileSize);
        this.level = level;
        this.directory = directory;
        this.maxFileSize = maxFileSize;
        this.enableConsoleLogging = enableConsoleLogging;
        this.info = setup(name + ":info", "info.log");
        this.error = setup(name + ":error", "error.log");
        this.warn = setup(name + ":warn", "warn.log");
        this.debug = setup(name + ":debug", "debug.log");
    }

    /**
     * Print a message to the DEBUG log.
     * 
     * @param format the message format
     * @param params the message parameters
     */
    public void debug(String format, Object... params) {
        debug.debug(format, params);
    }

    /**
     * Print a message to the ERROR log.
     * 
     * @param format the message format
     * @param params the message parameters
     */
    public void error(String format, Object... params) {
        error.error(format, params);
    }

    /**
     * Print a message to the INFO log.
     * 
     * @param format the message format
     * @param params the message parameters
     */
    public void info(String format, Object... params) {
        info.info(format, params);
    }

    /**
     * Intercept the logging for {@code clazz} and route it to this Logger at
     * the specified {@code level}.
     * 
     * @param clazz the {@link Class} whose logs should be intercepted
     * @param level the {@link Level} to use for the class's logs
     */
    public void intercept(Class clazz, Level level) {
        setup(clazz.getName(), level.levelStr.toLowerCase() + ".log");
    }

    /**
     * Print a message to the WARN log.
     * 
     * @param format the message format
     * @param params the message parameters
     */
    public void warn(String format, Object... params) {
        warn.warn(format, params);
    }

    /**
     * Programmatically configure an internal logger.
     * 
     * @param name the name of the internal logger
     * @param file the the internal logger uses
     * @return the internal logger
     */
    private ch.qos.logback.classic.Logger setup(String name, String file) {
        if(!enableConsoleLogging) {
            ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory
                    .getLogger(ch.qos.logback.classic.Logger.ROOT_LOGGER_NAME);
            root.detachAndStopAllAppenders();
        }
        LoggerContext context = (LoggerContext) LoggerFactory
                .getILoggerFactory();
        // Configure Pattern
        PatternLayoutEncoder encoder = new PatternLayoutEncoder();
        encoder.setPattern("%date [%thread] %level - %msg%n");
        encoder.setContext(context);
        encoder.start();

        // Create File Appender
        RollingFileAppender appender = new RollingFileAppender();
        appender.setFile(directory + File.separator + file);
        appender.setContext(context);

        // Configure Rolling Policy
        FixedWindowRollingPolicy rolling = new FixedWindowRollingPolicy();
        rolling.setMaxIndex(1);
        rolling.setMaxIndex(5);
        rolling.setContext(context);
        rolling.setFileNamePattern(
                directory + File.separator + file + ".%i.zip");
        rolling.setParent(appender);
        rolling.start();

        // Configure Triggering Policy
        SizeBasedTriggeringPolicy triggering = new SizeBasedTriggeringPolicy();
        triggering.setMaxFileSize(maxFileSize);
        triggering.start();

        // Configure File Appender
        appender.setEncoder(encoder);
        appender.setRollingPolicy(rolling);
        appender.setTriggeringPolicy(triggering);
        appender.start();

        // Get Logger
        ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory
                .getLogger(name);
        logger.addAppender(appender);
        logger.setLevel(level);
        logger.setAdditive(true);
        return logger;
    }

    /**
     * The builder...
     * 
     * @author Jeff Nelson
     */
    public static class Builder {
        private String directory;

        private boolean enableConsoleLogging = false;
        private Level level = Level.INFO;
        private String maxFileSize = "10MB";
        private String name;

        private Builder() {/* no-op */}

        /**
         * Builder the {@link Logger}.
         * 
         * @return the Logger
         */
        public Logger build() {
            return new Logger(name, level, directory, maxFileSize,
                    enableConsoleLogging);
        }

        /**
         * Set the directory in which the log files are placed.
         * 
         * @param directory the log directory
         * @return the builder
         */
        public Builder directory(String directory) {
            this.directory = directory;
            return this;
        }

        /**
         * Specify whether the returned {@link Logger} should log to the
         * console.
         * 
         * @param enable a boolean that indicates if consle logging should be
         *            enabled
         * @return this
         */
        public Builder enableConsoleLogging(boolean enable) {
            this.enableConsoleLogging = enable;
            return this;
        }

        /**
         * Set the log {@link Level level} of the returned instance.
         * 
         * @param level the log level
         * @return the builder
         */
        public Builder level(Level level) {
            this.level = level;
            return this;
        }

        /**
         * Set the maximum size to allow a log file to grow before rolling.
         * 
         * @param maxFileSize the max log file size
         * @return the builder
         */
        public Builder maxFileSize(String maxFileSize) {
            this.maxFileSize = maxFileSize;
            return this;
        }

        /**
         * Set the name of the returned {@link Logger} instance.
         * 
         * @param name the logger name
         * @return the builder
         */
        public Builder name(String name) {
            this.name = name;
            return this;
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy