Log日志

Jingxc大约 3 分钟java后端logjava后端

Log日志

在完成日常任务时,有时候需要根据不同的目的,自己定制化完成log日志的输出,通过配置文件实现日志输出存在一定的局限性,可以通过代码来,定制化实现下面的目标

  • 自定义日志文件输出目录
  • 自定义日志文件名称格式
  • 自定义日志文件输出间隔
  • 自定义日志内容输出格式 ...

配置文件

package com.game.server.config;

import java.text.SimpleDateFormat;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.varia.LevelRangeFilter;

public class LoggerFactory {

    // 防止频繁创建Logger对象
    private static volatile Map<String, List<Object>> logMap = new ConcurrentHashMap<String, List<Object>>();

    public static Logger getLogger(String baseDir, String appId, String type) {

        SimpleDateFormat formatter = new SimpleDateFormat("'_'yyyyMMdd");
        String date = formatter.format(new Date());

        if (StringUtils.isEmpty(baseDir) || StringUtils.isEmpty(appId)) {
            throw new IllegalArgumentException("cannot be empty");
        }
        // 防止map过大不按时间存储{ key: [date_A, logger_A] }
        String key = baseDir + "/" + appId + "/gameserver_" + appId + "_" + type;

        List<Object> list = logMap.get(key);

        if (list == null) {
            // 存储新数据
            try {

                Logger logger = createLogger(key, type, date);
                return logger;

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        // 比较时间
        String saveDate = String.valueOf(list.get(0));
        if (saveDate.equals(date)) {
            Logger logger = (Logger) list.get(1);
            return logger;
        } else {
            try {
                // 更新数据
                Logger logger = createLogger(key, type, date);
                return logger;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 添加同步锁,并进行双端校验,防止重复创建
     * 
     * @param key
     * @param type
     * @param date
     * @return
     */
    private synchronized static Logger createLogger(String key, String type, String date) {

        // 双端检索,防止重复创建
        List<Object> list = logMap.get(key);

        if (list != null) {
            String saveDate = String.valueOf(list.get(0));
            if (saveDate.equals(date)) {
                Logger logger = (Logger) list.get(1);
                return logger;
            }
        }

        String logFilePath = key + date;
        // 添加Appender到日志记录器
        Logger logger = Logger.getLogger("com.game.server.config.LoggerFactory." + type + date);

        FileAppender appender = new FileAppender();

        // 设置输出文件名
        appender.setFile(logFilePath);
        // 设置输出格式
        appender.setLayout(new PatternLayout("%m%n"));
        // 设置Appender的阈值级别
        appender.setThreshold(Level.INFO);
        appender.activateOptions();

        LevelRangeFilter filterInfo = new LevelRangeFilter();
        filterInfo.setLevelMin(Level.INFO);
        filterInfo.setLevelMax(Level.ERROR);
        appender.addFilter(filterInfo);
        logger.addAppender(appender);

        list = new ArrayList<>();
        list.add(date);
        list.add(logger);

        logMap.put(key, list);

        return logger;
    }
}

配置介绍


本文采用log4j作为基础,使用时需要引入相关依赖

主要通过getLogger静态方法,获取日志Logger对象,入参是String baseDir, String appId, String type

  • baseDir设置日志存放根目录
  • appId区分不同日志目录
  • type区分日志文件类型

本文中采用的是每天自动生成新的日志文件,为了防止运行时占用堆空间过大,不以时间直接存储到logMap,这样既可以减少资源的占用,又可以减少Logger对象的频繁创建

主要是对比时间以及文件类型来判断是否需要创建Logger对象

提示

// 双端检索,防止重复创建
List<Object> list = logMap.get(key);

if (list != null) {
    String saveDate = String.valueOf(list.get(0));
    if (saveDate.equals(date)) {
        Logger logger = (Logger) list.get(1);
        return logger;
    }
}

这段代码比较重要,防止并发的时候重复创建日志记录器,

// 添加Appender到日志记录器 Logger logger = Logger.getLogger("com.game.server.config.LoggerFactory." + type + date);

日志使用

Logger logger = LoggerFactory.getLogger(cache.getBaseDir(), appid, CORE_LOG);
logger.info("[" + time + "][LogReg]," + JSON.toJSONString(params, SerializerFeature.WriteMapNullValue));
上次编辑于:
贡献者: Jingxc