将logback日志通过logback 自定义Appender组件输出到目标库中,以MongoDB为例
1.引入相关pom坐标,如果是springboot项目可以只需引入 mongodb的依赖,因为springboot本身默认使用logback
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>0.9.28</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>0.9.28</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.4.2</version>
</dependency>
2. 编写两个java类,用于定义MongoDB适配参数和文档内容,一个是 MongoDBAppenderBase ,另一个是MongoDBAppender
/**
* MongoDBAppender适配类
*/
public abstract class MongoDBAppenderBase<E> extends UnsynchronizedAppenderBase<E> {
private MongoClient mongo;
private MongoCollection<Document> eventsCollection;
private String host = "10.10.8.10"; // 地址
private int port = 27017; // 端口号
private String dbName = "db"; // 库名
private String collectionName; // 集合名
private String username; // 用户名
private String password; // 密码
protected String source;
private int connectionsPerHost = 10; // 空闲线程池中最大链接数
private int threadsAllowedToBlockForConnectionMultiplier = 5; //一个线程等待链接可用的最大等待毫秒数
private int maxWaitTime = 1000 * 60 * 2; // 最长等待时间
private int connectTimeout;
private int socketTimeout;
private int wtimeout;
MongoDBAppenderBase(String collectionName) {
this.collectionName = collectionName;
}
@Override
public void start() {
try {
connectToMongoDB();
super.start();
} catch (UnknownHostException e) {
addError( "Error connecting to MongoDB server: " + host + ":" + port,
e);
}
}
private void connectToMongoDB() throws UnknownHostException {
// 用户名 数据库 密码
if (username != null && password != null){
MongoCredential credential = MongoCredential.createCredential(username, dbName, password.toCharArray());
mongo = new MongoClient(new ServerAddress(host, port), Collections.singletonList(credential), buildOptions());
}else{
mongo = new MongoClient(new ServerAddress(host, port), buildOptions());
}
MongoDatabase db = mongo.getDatabase(dbName);
eventsCollection = db.getCollection(collectionName);
}
private MongoClientOptions buildOptions() {
final MongoClientOptions.Builder options = new MongoClientOptions.Builder();
options.connectionsPerHost(connectionsPerHost) ;
options.threadsAllowedToBlockForConnectionMultiplier(threadsAllowedToBlockForConnectionMultiplier) ;
options.maxWaitTime(maxWaitTime) ;
options.connectTimeout(connectTimeout) ;
options.socketTimeout(socketTimeout) ;
options.maxWaitTime(wtimeout) ;
return options.build();
}
protected abstract Document toMongoDocument(E event);
@Override
protected void append(E eventObject) {
eventsCollection.insertOne(toMongoDocument(eventObject));
}
@Override
public void stop() {
if (mongo != null)
mongo.close();
super.stop();
}
//... 以下是变量get set 方法 此处省略
/**
* MongoDB适配文档输出内容定义
*/
public class MongoDBAppender extends MongoDBAppenderBase<ILoggingEvent> {
public MongoDBAppender() {
super("loggingEvents");
}
@Override
protected Document toMongoDocument(ILoggingEvent eventObject) {
final Document doc = new Document();
//doc.append("date", new JDateTime(eventObject.getTimeStamp()).toString("YYYY-MM-DD hh:mm:ss"));
doc.append("date",new Date());
doc.append("source", source);
doc.append("level", eventObject.getLevel().toString());
doc.append("logger", eventObject.getLoggerName());
doc.append("thread", eventObject.getThreadName());
doc.append("message", eventObject.getFormattedMessage());
if (eventObject.getMDCPropertyMap() != null && !eventObject.getMDCPropertyMap().isEmpty())
doc.append("mdc", eventObject.getMDCPropertyMap());
// ...
return doc;
}
}
3.在项目src/main/resource 目录下 添加 logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">
<include resource="org/springframework/boot/logging/logback/base.xml" />
<!-- CONTEXT -->
<property name="CONTEXT_NAME" value="xxx-xxx-service" />
<contextName>${CONTEXT_NAME}</contextName>
<!-- 彩色日志配置 -->
<!-- 彩色日志依赖的渲染类 -->
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
<!-- 彩色日志格式 -->
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){green} %clr(${LOG_LEVEL_PATTERN:-%5p}){red} %clr(${PID:-}){magenta} %clr(---){blue} %clr([%30.30t]){yellow} %clr(%-40.40logger{39}){cyan} %clr(:){blue} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}" />
<!-- 日志控制台输出设置 -->
<!-- %m输出的信息,%p日志级别,%t线程名,%d日期,%c类的全名 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<!-- <pattern>%d %p (%file:%line\)- %m%n</pattern> -->
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- 文件输出设置 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>../logs/${CONTEXT_NAME}/${CONTEXT_NAME}.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>../logs/${CONTEXT_NAME}/${CONTEXT_NAME}.%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<!-- mongoDB输出设置,此处是定义 -->
<appender name="MONGO" class="com.xxx.logback.classic.db.ext.MongoDBAppender">
<host>10.10.8.10</host>
<port>27017</port>
<!-- <username>lzw</username> -->
<!-- <password>123</password> -->
<dbName>logdb</dbName>
<collectionName>logdb</collectionName>
<source>${CONTEXT_NAME}</source>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>WARN</level>
</filter>
</appender>
<!-- 总开关 -->
<root level="info">
<!-- <appender-ref ref="CONSOLE" /> -->
<appender-ref ref="FILE" />
<appender-ref ref="MONGO" />
</root>
</configuration>
4.输出结果