【问题标题】:How to integrate programmatic configuration in log4j?如何在 log4j 中集成编程配置?
【发布时间】:2018-10-18 11:59:44
【问题描述】:

我使用的是Log4j 2.0.1版本,由于组织政策,我暂时不能使用更高版本。

group:'org.apache.logging.log4j',name:'log4j-core',version:'2.0.1'
group:'org.apache.logging.log4j',name:'log4j-api',version:'2.0.1'

我的日志记录要求

  1. 如果 customDebug=true 作为环境变量,则启用调试日志记录
  2. 应该生成 2 个日志记录文件 - 一个主日志记录(基于上述日志的信息/调试)和错误日志记录。
  3. 拥有基于尺寸的滚动策略
  4. 日志文件的目录是动态的。
  5. 格式应带有特定样式的时间以及线程 ID。

我尝试通过以下方式实现 log4j 的编程配置 --

CustomConfigFactory.java >>

@Plugin(name = "CustomConfigFactory", category = "JsonConfigurationFactory")
@Order(10)
public class CustomConfigFactory extends JsonConfigurationFactory {

    @Override
    public String[] getSupportedTypes() {
        return new String[] {".json"};
    }

    @Override
    public Configuration getConfiguration(ConfigurationSource cs) {
        try{
            String file = Thread.currentThread().getContextClassLoader().getResource("customRollingConfiguration.json").getFile()
            cs = new ConfigurationSource(new FileInputStream(new File(file ));
        } catch (Exception e){
            System.err.println("ERROR : Exception encountered while initiating configuration source: "+e);
        }
        return new CustomJsonConfiguration(cs);
    }

}

CustomJsonConfiguration.java >>

public class CustomJsonConfiguration extends JsonConfiguration {

    public CustomJsonConfiguration(final ConfigurationSource configSource) {
        super(configSource);
    }

    @Override
    protected void doConfigure(){
        try {
            ConfigurationSource source = this.getConfigurationSource();
            Configuration config = CustomConfigFactory.getInstance().getConfiguration(source);

            final Layout layout = PatternLayout.createLayout("%d{yyyy-MM-dd HH:mm:ss.SSS} %-5p [%5T] %c{1}:%L - %m%n",
                config,null,Charset.defaultCharset(),true,false,"","");

            SizeBasedTriggeringPolicy policy = SizeBasedTriggeringPolicy.createPolicy("10 MB");
            DefaultRolloverStrategy strategy = DefaultRolloverStrategy.createStrategy("50", "5", "min", "9", config);

            String logDir = System.getenv("log_dir");
            String primaryLogFile = logDir+"/my_main_log";
            String primaryLogFilePattern = primaryLogFile+"-backup-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz";

            String errorLogFile = logDir+"/my_err_log";
            String errorLogFilePattern = errorLogFile+"-backup-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz";

            RollingFileAppender appender1 = RollingFileAppender.createAppender(primaryLogFile,
                primaryLogFilePattern,"true", "debugFile","true", "false","false",
                policy, strategy, layout, null, null, null, null, config);
            appender1.start();;

            RollingFileAppender appender2 = RollingFileAppender.createAppender(errorLogFile,
                errorLogFilePattern,"true","errorFile","true","false","false",
                policy, strategy, layout, null,null,null,null, config);
            appender2.start();;

            config.addAppender(appender1);
            config.addAppender(appender2);

            LoggerConfig primaryLoggerConfig = null;
            if(Boolean.valueOf(System.getenv("customDebug")){
                 primaryLoggerConfig = new LoggerConfig("aa.bb.cc.dd",Level.DEBUG,false);
            } else {
                primaryLoggerConfig = new LoggerConfig("aa.bb.cc.dd",Level.INFO,false);
            }
            LoggerConfig errorLoggerConfig = new LoggerConfig("aa.bb.cc.dd",Level.ERROR,false);

            primaryLoggerConfig.addAppender(appender1,null,null);
            errorLoggerConfig.addAppender(appender2,null,null);
            config.addLogger("aa.bb.cc.dd",primaryLoggerConfig);
            config.addLogger("aa.bb.cc.dd",errorLoggerConfig);

            LoggerContext context = new LoggerContext("default_context");
            context.start(config);
        } catch (Exception e){
            System.err.println("");
        }
    }

其中 aa.bb.cc.dd 指的是下面 MyClass 的包名。

MyClass.java 记录器将在哪里使用 >>

package aa.bb.cc.dd;

public MyClass {
    static final Logger myCustomLog = LogManager.getLogger(MyClass.class);

    void doSomething(){
        myCustomLog.info("Doing something");
    }
}

示例测试方法作为 testng 类的一部分,用于测试上述类 >>>

@Test
public void testDoingSomething(){
    MyClass m1 = new MyClass();
    m1.doSomething();
}

但上述方法似乎不起作用,并且没有生成任何日志文件,即日志记录不起作用。 我主要参考了这个来实现--https://logging.apache.org/log4j/2.x/manual/customconfig.html#Hybrid

如果有人可以帮助我完成此实施,我将不胜感激。欢迎所有建议!!!

提前致谢。

编辑 >>> 以下是合并@VikasSachdeva 的 cmets 后的配置 json。即使在 my_main.log 中记录了错误条件,错误文件仍然为空

{
  "configuration": {
     "name": "RollingKitConfig",
    "Appenders": {
  "appender": [
    {
      "type": "RollingFile",
      "name": "debugFile",
      "fileName": "${env:log_dir}/my_main_log",
      "filePattern": "${env:log_dir  }/my_main_backup-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz",
      "PatternLayout": {
        "pattern": "%d{yyyy-MM-dd HH:mm:ss,nnn} [%-5p] [%5t] [%c{3}:%L] - %m%n"
      },
      "Policies": {
        "SizeBasedTriggeringPolicy": {
          "size": "10 MB"
        }
      },
      "DefaultRolloverStrategy": {
        "max": "10"
      },
      "ThresholdFilter": {
        "level": "${env:customDebug:-info}"
      }
    },
    {
      "type": "RollingFile",
      "name": "errorFile",
      "fileName": "${env:log_dir}/errors.log",
      "filePattern": "${env:log_dir}/errors_backup-%d{MM-dd-yy-HH-mm-ss}-%i.log.gz",
      "PatternLayout": {
        "pattern": "%d{yyyy-MM-dd HH:mm:ss,nnn} [%-5p] [%5t] [%c{1}:%L] - %m%n"
      },
      "Policies": {
        "SizeBasedTriggeringPolicy": {
          "size": "10 MB"
        }
      },
      "DefaultRolloverStrategy": {
        "max": "10"
      },
      "ThresholdFilter": {
        "level": "ERROR",
        "onMatch": "ACCEPT",
        "onMisMatch": "DENY"
      }
    }
  ]
},
"Loggers": {
  "logger": [
    {
      "name": "KitLogger",
      "level": "info",
      "additivity": "false",
      "AppenderRef": [
        {
          "ref": "debugFile"
        },
        {
          "ref": "errorFile"
        }
      ]
    }
  ],
  "root": {
    "level": "debug",
    "appender-ref": {
      "ref": "debugFile"
    }
  }
}
  }
}

【问题讨论】:

  • 您提到的实现是混合实现,即配置文件+程序修改。那么,您是否使用任何配置文件。可以发一下吗?
  • @VikasSachdeva -- 谢谢。添加了配置json文件。因此,由于日志文件位置是动态的,因此 json 文件没有日志文件的任何路径或名称。请提出建议。

标签: java logging log4j2 rollingfileappender programmatic-config


【解决方案1】:

如果您只想使用环境变量选择日志文件位置,您可以单独使用配置文件,如log4j2 documentation 中所述

考虑到您的环境变量是log_dir=D:/logs/。然后你可以像下面这样改变你的配置 -

{
    "configuration": {
        "name": "RollingConfig",
        "ThresholdFilter": { "level": "info" },
        "properties": {
            "property": {
                "name": "basePath",
                "value": "${env:log_dir}"
             }
        },
        "appenders": {
            "RollingFile": {
                "name": "debugFile",
                "fileName": "${basePath}my_main.log",
                "filePattern": "${basePath}my_main_%d{yyyyMMdd}.log.gz",
                "PatternLayout": { "pattern": "%d{yyyy-MM-dd HH:mm:ss} %-5p [%5T] %c{1}:%L - %m%n" },
                "Policies": {
                    "SizeBasedTriggeringPolicy": { "size": "10 MB" }
                },
               "DefaultRolloverStrategy": { "max": "10"  }
            },
            "RollingFile": {
                "name": "errorFile",
                "fileName": "${basePath}my_err.log",,
                "filePattern": "${basePath}my_err_%d{yyyyMMdd}.log.gz",
                "thresholdFilter": {
                    "level": "ERROR",
                    "onMatch": "ACCEPT",
                    "onMisMatch": "DENY"
                },
                "PatternLayout": { "pattern": "%d{yyyy-MM-dd HH:mm:ss} %-5p [%5T] %c{1}:%L - %m%n" },
                "Policies": {
                     "SizeBasedTriggeringPolicy": {  "size": "10 MB" }
                },
                "DefaultRolloverStrategy": {"max": "10"}
            }
        },
        "loggers": {
            "logger": {
                 "name": "mainLogger",
                 "level": "info",
                 "additivity": "false",
                 "appender-ref": [ 
                                 {"ref": "debugFile"}, 
                                 { "ref":"errorFile"}
                                 ]
            },
            "root": {
                "level": "info",
                 "appender-ref": [ 
                                 {"ref": "debugFile" }, 
                                 { "ref":"errorFile" }
                                 ]
             }
          }
       }
}

【讨论】:

  • 谢谢@VikasSachdeva。还有 1 个问题 - 我希望 errorFile appender 只记录 ERROR 消息。我尝试使用阈值过滤器,但它似乎不起作用。任何输入?
  • 我用errorFile appender上的阈值过滤器配置更新了上面的答案。
  • 错误文件仍然没有记录错误消息,虽然 ERROR 被记录在主 debugFile 而不是 errorFile。
  • 你也在记录器中添加了附加程序?你能发布你更新的配置吗
  • 现在更新了 json 文件。错误案例对我不起作用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-09-02
  • 1970-01-01
  • 1970-01-01
  • 2012-02-16
  • 1970-01-01
  • 2019-08-15
  • 2011-07-04
相关资源
最近更新 更多