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

com.alibaba.csp.sentinel.log.LogBase Maven / Gradle / Ivy

There is a newer version: 2.0.0-alpha
Show newest version
/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * 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.alibaba.csp.sentinel.log;

import java.io.File;
import java.io.IOException;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;

import com.alibaba.csp.sentinel.util.PidUtil;
import com.alibaba.csp.sentinel.util.StringUtil;

/**
 * Default log base dir is ${user.home}/logs/csp/, we can use {@link #LOG_DIR} System property to override it.
 * Default log file name dose not contain pid, but if multi instances of the same app are running in the same
 * machine, we may want to distinguish the log file by pid number, in this case, {@link #LOG_NAME_USE_PID}
 * System property could be configured as "true" to turn on this switch.
 *
 * @author leyou
 */
public class LogBase {

    public static final String LOG_CHARSET = "utf-8";

    // Output biz log(RecordLog,CommandCenterLog) to file
    public static final String LOG_OUTPUT_TYPE_FILE = "file";
    // Output biz log(RecordLog,CommandCenterLog) to console
    public static final String LOG_OUTPUT_TYPE_CONSOLE = "console";

    private static final String DIR_NAME = "logs" + File.separator + "csp";
    private static final String USER_HOME = "user.home";

    // Output type of biz log(RecordLog,CommandCenterLog)
    public static final String LOG_OUTPUT_TYPE = "csp.sentinel.log.output.type";
    public static final String LOG_DIR = "csp.sentinel.log.dir";
    public static final String LOG_NAME_USE_PID = "csp.sentinel.log.use.pid";

    private static String logOutputType;
    private static String logBaseDir;
    private static boolean logNameUsePid = false;

    static {
        try {
            init();
        } catch (Throwable t) {
            System.err.println("[LogBase] FATAL ERROR when initializing log class");
            t.printStackTrace();
        }
    }

    private static void init() {
        logOutputType = System.getProperty(LOG_OUTPUT_TYPE);

        // By default, output biz log(RecordLog,CommandCenterLog) to file
        if (StringUtil.isBlank(logOutputType)) {
            logOutputType = LOG_OUTPUT_TYPE_FILE;
        } else if (!LOG_OUTPUT_TYPE_FILE.equalsIgnoreCase(logOutputType) && !LOG_OUTPUT_TYPE_CONSOLE.equalsIgnoreCase(logOutputType)) {
            logOutputType = LOG_OUTPUT_TYPE_FILE;
        }

        // first use -D, then use user home.
        String logDir = System.getProperty(LOG_DIR);

        if (logDir == null || logDir.isEmpty()) {
            logDir = System.getProperty(USER_HOME);
            logDir = addSeparator(logDir) + DIR_NAME + File.separator;
        }
        logDir = addSeparator(logDir);
        File dir = new File(logDir);
        if (!dir.exists()) {
            if (!dir.mkdirs()) {
                System.err.println("ERROR: create log base dir error: " + logDir);
            }
        }
        // logBaseDir must end with File.separator
        logBaseDir = logDir;
        System.out.println("INFO: log base dir is: " + logBaseDir);

        String usePid = System.getProperty(LOG_NAME_USE_PID, "");
        logNameUsePid = "true".equalsIgnoreCase(usePid);
        System.out.println("INFO: log name use pid is: " + logNameUsePid);
    }

    /**
     * Whether log file name should contain pid. This switch is configured by {@link #LOG_NAME_USE_PID} System property.
     *
     * @return if log file name should contain pid, return true, otherwise return false.
     */
    public static boolean isLogNameUsePid() {
        return logNameUsePid;
    }

    private static String addSeparator(String logDir) {
        if (!logDir.endsWith(File.separator)) {
            logDir += File.separator;
        }
        return logDir;
    }

    protected static void log(Logger logger, Handler handler, Level level, String detail, Object... params) {
        if (detail == null) {
            return;
        }
        LoggerUtils.disableOtherHandlers(logger, handler);
        if (params.length == 0) {
            logger.log(level, detail);
        } else {
            logger.log(level, detail, params);
        }
    }

    protected static void log(Logger logger, Handler handler, Level level, String detail, Throwable throwable) {
        if (detail == null) {
            return;
        }
        LoggerUtils.disableOtherHandlers(logger, handler);
        logger.log(level, detail, throwable);
    }

    /**
     * Get log file base directory path, the returned path is guaranteed end with {@link File#separator}
     *
     * @return log file base directory path.
     */
    public static String getLogBaseDir() {
        return logBaseDir;
    }

    protected static Handler makeLogger(String logName, Logger heliumRecordLog) {
        CspFormatter formatter = new CspFormatter();

        Handler handler = null;

        // Create handler according to logOutputType, set formatter to CspFormatter, set encoding to LOG_CHARSET
        switch (logOutputType) {
            case LOG_OUTPUT_TYPE_FILE:
                String fileName = LogBase.getLogBaseDir() + logName;
                if (isLogNameUsePid()) {
                    fileName += ".pid" + PidUtil.getPid();
                }
                try {
                    handler = new DateFileLogHandler(fileName + ".%d", 1024 * 1024 * 200, 4, true);
                    handler.setFormatter(formatter);
                    handler.setEncoding(LOG_CHARSET);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            case LOG_OUTPUT_TYPE_CONSOLE:
                try {
                    handler = new ConsoleHandler();
                    handler.setFormatter(formatter);
                    handler.setEncoding(LOG_CHARSET);
                } catch (IOException e) {
                    e.printStackTrace();
                }
                break;
            default:
                break;
        }

        if (handler != null) {
            LoggerUtils.disableOtherHandlers(heliumRecordLog, handler);
        }
        heliumRecordLog.setLevel(Level.ALL);
        return handler;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy