1. 引言
通常情况下,对于SpringBoot微服务,会在logback-spring.xml中配置日志。但有的情况下,可能无法事前配置或者在logback-spring.xml中配置不是最有选择。例如以下情形:
情形一:有一个Job调度服务其中运行不定数量的Job。运行多少个以及运行哪些Job,完全由用户配置。要求将这些Job的日志输出到不同的日志文件中。
情形二:有一个应用,需要将其中某一模块的日志输出到Kafka。Kafka的联系信息存储在Zookeeper中。出于尽可能减少重复配置的原因,并不想在logback-spring.xml或者命令行参数中指定。而且也不想在SpringApp启动之间,加一些连接Zookeper,读取配置的操作,因为应用的配置,Zookeepr连接,都已经是SpringApp启动过程中的工作了。所以想在应用启动过程中加载应用配置,连接Zookeeper,然后在模块初始化时,读取Kafka连接信息,再添加appener。
2 . 代码
Context loggerCtx = (LoggerContext)LoggerFactory.getILoggerFactory() ;
KafkaAppender<ILoggingEvent> appender = new KafkaAppender<>();
// 这里设置过滤器
appender.addFilter(new Filter<ILoggingEvent>()
{
@Override
public FilterReply decide(ILoggingEvent aEvent)
{
return aEvent.getLoggerName().startsWith("flink_log.")?FilterReply.ACCEPT:FilterReply.DENY ;
}
}) ;
// 设置上下文,每个logger都关联到logger上下文,默认上下文名称为default。
// 但可以使用<scope="context">设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改。
appender.setContext(loggerCtx);
// appender的name属性
appender.setName("kafka");
String bootServers = ZKSysProxy.getSysDefault().getKafkaBootstrapServers() ;
appender.addProducerConfigValue("bootstrap.servers" , bootServers) ;
appender.addProducerConfigValue("auto.commit.interval.ms" , 1_000);
appender.setTopic("_log_flink") ;
appender.setEncoder(createEncoder(loggerCtx));
appender.start();
((LoggerContext)loggerCtx).getLogger(Logger.ROOT_LOGGER_NAME).addAppender(appender);
mLogger.info("日志写入Kafka集群:{}" , bootServers) ;
... 省略
private static PatternLayoutEncoder createEncoder(Context aLoggerCtx)
{
PatternLayoutEncoder encoder = new PatternLayoutEncoder();
// 设置上下文,每个logger都关联到logger上下文,默认上下文名称为default。
// 但可以使用<scope="context">设置成其他名字,用于区分不同应用程序的记录。一旦设置,不能修改。
encoder.setContext(aLoggerCtx);
// 设置格式
String pattern = OptionHelper.substVars(
"%X{where}.%X{logTime}.0 %d{MM-dd HH:mm:ss.SSS} %-5level %logger{0} L:%L -%msg%n",
aLoggerCtx);
encoder.setPattern(pattern);
encoder.setCharset(AppContext.sUTF8);
encoder.start();
return encoder;
}