logback如何自定義日志存儲
更新時間:2021年08月30日 10:44:43 作者:吾追無所求
這篇文章主要介紹了logback如何自定義日志存儲的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
logback自定義日志存儲
1、配置lockback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="LOG_HOME" value="/wzwsq-log" />
<property name="APP_NAME" value="wzwsq" />
<!-- 控制臺輸出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日志消息,%n是換行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %X{address} %-5level %logger{50} - %msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件輸出的文件名 -->
<FileNamePattern>${LOG_HOME}/${APP_NAME}.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天數(shù) -->
<MaxHistory>10</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化輸出:%d表示日期,%thread表示線程名,%-5level:級別從左顯示5個字符寬度%msg:日志消息,%n是換行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %X{address} %-5level %logger{50} - %msg%n</pattern>
<!--<pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern> -->
</encoder>
</appender>
<!--連接數(shù)據(jù)庫配置 class:日志保存操作類 -->
<appender name="db_classic_mysql_pool" class="wzwsq.config.LogDBAppender">
<connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
<dataSource class="org.apache.commons.dbcp.BasicDataSource">
<driverClassName>com.mysql.jdbc.Driver</driverClassName>
<url>jdbc:mysql://localhost:3306/wzwsq?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf8</url>
<username>root</username>
<password>123456</password>
</dataSource>
</connectionSource>
</appender>
<!-- 日志輸出級別 -->
<root level="info">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
<!--添加自定義操作配置-->
<appender-ref ref="db_classic_mysql_pool" />
</root>
</configuration>
2、配置自定義日志操作類
import ch.qos.logback.classic.spi.CallerData;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.db.DBAppenderBase;
import com.alibaba.fastjson.JSONObject;
import wzwsq.model.IpInfo; //自定義IP對象
import wzwsq.model.UsersModel; //自定義用戶對象
import wzwsq.util.Constant; //自定義常量對象
import wzwsq.util.WebUtils; //自定義Web工具對象
import org.springframework.context.annotation.Configuration;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
/**
* @ClassName LogDBAppender
* @Description: 自定義日志保存至數(shù)據(jù)庫
* @Author wzwsq
* @Date 2020/12/10
* @Version V1.0
**/
@Configuration
public class LogDBAppender extends DBAppenderBase<ILoggingEvent> {
protected static final Method GET_GENERATED_KEYS_METHOD;
//插入sql
protected String insertSQL;
//自定義存儲字段
/**
* menu_type:操作類型,指的是菜單ID
* record_id:相關(guān)操作對象的ID
* operation_content:操作內(nèi)容,自定義編輯
* add_id:操作人ID
* add_time:操作時間
* ip:根據(jù)IP對應城市
* city:ip所屬城市
* ua:瀏覽器信息
* */
static final int MENU_TYPE = 1;
static final int RECORD_ID = 2;
static final int OPERATION_CONTENT = 3;
static final int ADD_ID = 4;
static final int ADD_TIME = 5;
static final int IP = 6;
static final int CITY = 7;
static final int UA = 8;
static final StackTraceElement EMPTY_CALLER_DATA = CallerData.naInstance();
static {
// PreparedStatement.getGeneratedKeys() method was added in JDK 1.4
Method getGeneratedKeysMethod;
try {
// the
getGeneratedKeysMethod = PreparedStatement.class.getMethod("getGeneratedKeys", (Class[]) null);
} catch (Exception ex) {
getGeneratedKeysMethod = null;
}
GET_GENERATED_KEYS_METHOD = getGeneratedKeysMethod;
}
@Override
public void start() {
// 將寫好的sql語句賦值給insertSQL
insertSQL = buildInsertSQL();
super.start();
}
// 自己寫新增sql語句
private static String buildInsertSQL() {
return "INSERT INTO `operation_log`" +
"(" +
"`menu_type`,`record_id`," +
"`operation_content`,`add_id`," +
"`add_time`,`ip`," +
"`city`,`ua`" +
")" +
"VALUES (?,?,?,?,?,?,?,?)";
}
@Override
protected Method getGeneratedKeysMethod() {
return GET_GENERATED_KEYS_METHOD;
}
@Override
protected String getInsertSQL() {
return insertSQL;
}
/**
* 主要修改的方法
*
* @param stmt
* @param event
* @throws SQLException
*/
private void bindLoggingEventWithInsertStatement(PreparedStatement stmt, ILoggingEvent event) throws SQLException {
// event.getFormattedMessage() 日志打印內(nèi)容
String message = event.getFormattedMessage();
// 如果只想存儲自己打印的日志,可以這樣寫日志:
// logger.info("'MENU_TYPE': '{}','RECORD_ID': '{}','OPERATION_CONTENT': '{}'",XXX,XXX,XXX)
//判斷當前日志信息是否屬于自定義類型
int MENU_TYPE_FLAG=message.indexOf("MENU_TYPE");
int RECORD_ID_FLAG=message.indexOf("RECORD_ID");
int OPERATION_CONTENT_FLAG=message.indexOf("OPERATION_CONTENT");
if(MENU_TYPE_FLAG>0&&RECORD_ID_FLAG>0&&OPERATION_CONTENT_FLAG>0){
//截取用戶自定義的日志信息
JSONObject jsonObject =JSONObject.parseObject(message);
String menuType=jsonObject.get("MENU_TYPE").toString();
String recordId=jsonObject.get("RECORD_ID").toString();
String operationContent=jsonObject.get("OPERATION_CONTENT").toString();
//獲取當前使用系統(tǒng)的用戶對象、IP、CITY、UA
UsersModel usersModel=WebUtils.getUser();//用戶登錄對象
IpInfo ipInfo=(IpInfo)WebUtils.getSession().getAttribute(Constant.IP_INFO);//用戶登錄IP信息
String ip=ipInfo.getIp();
String city=ipInfo.getCity();
String ua=ipInfo.getUa();
stmt.setString(MENU_TYPE, menuType);
stmt.setString(RECORD_ID, recordId);
stmt.setString(OPERATION_CONTENT, operationContent);
stmt.setString(ADD_ID,usersModel.getId().toString());
stmt.setTimestamp(ADD_TIME, new Timestamp(event.getTimeStamp()));
stmt.setString(IP, ip);
stmt.setString(CITY,city==null?"":city.toString());
stmt.setString(UA, ua==null?"":ua.toString());
}
}
@Override
protected void subAppend(ILoggingEvent eventObject, Connection connection, PreparedStatement statement) throws Throwable {
bindLoggingEventWithInsertStatement(statement, eventObject);
// This is expensive... should we do it every time?
int updateCount = statement.executeUpdate();
if (updateCount != 1) {
addWarn("Failed to insert loggingEvent");
}
}
@Override
protected void secondarySubAppend(ILoggingEvent eventObject, Connection connection, long eventId) throws Throwable {
}
}
3、調(diào)用方法
private static Logger logger = LoggerFactory.getLogger(UsersController.class);
logger.info("'MENU_TYPE': '{}','RECORD_ID': '{}','OPERATION_CONTENT': '{}'",XXX,XXX,XXX);
注意事項:在logback.xml中appender標簽一定的寫在root標簽之前
使用logback進行系統(tǒng)日志記錄
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.1.11</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.1.11</version>
</dependency>
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="log.base" value="/data1/logs/applogs/dt-mapping-api" />
<appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date %.-5level %class{100} ----------->> %msg%n</pattern>
</encoder>
</appender>
<appender name="logfile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.base}/default.log</file>
<!-- 配置日志所生成的目錄以及生成文件名的規(guī)則 在logs/mylog-2017-06-31.0.log.zip -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.base}.%d{yyyy-MM-dd}.%i.zip</fileNamePattern>
<!-- 如果按天來回滾,則最大保存時間為30天,30天之前的都將被清理掉 -->
<maxHistory>30</maxHistory>
<!-- 日志總保存量為10GB -->
<totalSizeCap>10 GB</totalSizeCap>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!--文件達到 最大128MB時會被壓縮和切割 -->
<maxFileSize>128 MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %.-5level %class{25} - %msg%n</pattern>
</encoder>
</appender>
<appender name="errorfile"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.base}/error.log</file>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
<!-- 配置日志所生成的目錄以及生成文件名的規(guī)則 在logs/mylog-2017-06-31.0.log.zip -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.base}/error.%d{yyyy-MM-dd}.%i.zip</fileNamePattern>
<!-- 如果按天來回滾,則最大保存時間為30天,30天之前的都將被清理掉 -->
<maxHistory>30</maxHistory>
<!-- 日志總保存量為10GB -->
<totalSizeCap>10 GB</totalSizeCap>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<!--文件達到 最大128MB時會被壓縮和切割 -->
<maxFileSize>128 MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
</rollingPolicy>
<encoder>
<pattern>%date [%thread] %.-5level %class{25} - %msg%n</pattern>
</encoder>
</appender>
<logger name="com.netflix.curator" level="OFF" />
<root level = "DEBUG">
<appender-ref ref="errorfile" />
<appender-ref ref="logfile" />
<appender-ref ref="stdout" />
</root>
</configuration>
private final static Logger logger = LoggerFactory.getLogger(Application.class);
logger.info("批次號: {}",111111111111);
logger.error("xxx失敗: {}",e);
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解Java的Struts2框架的結(jié)構(gòu)及其數(shù)據(jù)轉(zhuǎn)移方式
這篇文章主要介紹了詳解Java的Struts2框架的結(jié)構(gòu)及其數(shù)據(jù)轉(zhuǎn)移方式,Struts框架是Java的SSH三大web開發(fā)框架之一,需要的朋友可以參考下2016-01-01
springboot @Value實現(xiàn)獲取計算機中絕對路徑文件的內(nèi)容
這篇文章主要介紹了springboot @Value實現(xiàn)獲取計算機中絕對路徑文件的內(nèi)容,具有很好的參考價值,希望對大家有所幫助。2021-09-09
springboot解決java.lang.ArrayStoreException異常
這篇文章介紹了springboot解決java.lang.ArrayStoreException異常的方法,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2021-12-12
Swagger2不被SpringSecurity框架攔截的配置及說明
這篇文章主要介紹了Swagger2不被SpringSecurity框架攔截的配置及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03

