logback如何自定义日志存储

目录
  • logback自定义日志存储
    • 1、配置lockback.xml
    • 2、配置自定义日志操作类
    • 3、调用方法
  • 使用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>
   <!--日志文件保留天数 -->
   <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>
 <!--连接数据库配置 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&amp;useSSL=false&amp;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: 自定义日志保存至数据库
 * @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:相关操作对象的ID
     * operation_content:操作内容,自定义编辑
     * add_id:操作人ID
     * add_time:操作时间
     * ip:根据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() 日志打印内容
        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();
            //获取当前使用系统的用户对象、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、调用方法

private static Logger logger = LoggerFactory.getLogger(UsersController.class);
logger.info("'MENU_TYPE': '{}','RECORD_ID': '{}','OPERATION_CONTENT': '{}'",XXX,XXX,XXX);

注意事项:在logback.xml中appender标签一定的写在root标签之前

使用logback进行系统日志记录

<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>
         <!-- 配置日志所生成的目录以及生成文件名的规则 在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>
		<!-- 配置日志所生成的目录以及生成文件名的规则 在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);

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Logback日志基础及自定义配置代码实例

    Logback日志基础配置 logback日志配置有很多介绍,但是有几个非常基础的,容易忽略的.下面是最简单的一个配置,注意加粗的描述 <?xml version="1.0" encoding="UTF-8"?> <configuration debug="true" scan="true" scanPeriod="30 seconds"> <!--log.path定义的是局部

  • springboot实现将自定义日志格式存储到mongodb中

    步骤如下 首先定义封装所需要的日志信息的实体类 public class MyLog { //根据需要定义字段 @Id private String id; private Date ts; private String level; private String msg; private String thread; //属性的get/set方法(略) } 定义操作mongodb的接口 @Repository public interface LogRepository extends Mon

  • Logback日志存放路径不统一解决方案

    问题: 将一个应用程序打成了Jar包后,使用命令运行jar包,发现日志存放的路径并不统一: 比如 hello.jar 包放在 /aaa/bbb 目录下 如果在 /aaa/bbb 目录下执行:java -jar hello.jar ,那么日志就会存放在 /aaa/bbb 目录下 如果在 /aaa 目录下执行:java -jar bbb/hello.jar ,那么日志就会存放在 /aaa 目录下 如何才能不同位置执行jar包,但是日志放到一个统一的目录中呢? 解决过程: 查看logback.xml中

  • logback如何自定义日志存储

    目录 logback自定义日志存储 1.配置lockback.xml 2.配置自定义日志操作类 3.调用方法 使用logback进行系统日志记录 logback自定义日志存储 1.配置lockback.xml <?xml version="1.0" encoding="UTF-8"?> <configuration> <property name="LOG_HOME" value="/wzwsq-log&q

  • Laravel5.5以下版本中如何自定义日志行为详解

    前言 在 Laravel 5.6 版本中日志行为可以很容易的进行自定义,而在5.5以下版本中日志行为自定义自由度并不是很高,但是项目有需求不能因为这个就强行将项目升级为5.6吧,况且作为一个稳定的项目升级框架大版本有可能会有很多坑,基于这些原因我尝试了对 Laravel 5.5 的日志进行改造以适应我的需求. Laravel 的日志行为大部分是在 Illuminate\Log\LogServiceProvider 中,我们可以看一下其中的代码片段: /** * Configure the Mon

  • springboot logback调整mybatis日志级别无效的解决

    现象 在日志配置文件 logback-spring.xml 中,无论怎么修改级别,mybatis 的 sql 日志都会打印出来. 原因 在 application.yml 中配置了 mybatis 的自定义日志类,如下: mybatis: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl 点进去查看源码,发现 debug 日志级别始终为 true,所以怎么配置都不生效 public boolean isDeb

  • logback过滤部分日志输出的操作

    目录 logback过滤部分日志输出 场景 日志过滤 Logback 自定义灵活的日志过滤规则 下面是一个只记录日志级别为ERROR的例子 下面举一个简单的例子 logback过滤部分日志输出 场景 使用监控异常日志进行告警时,部分异常日志可能只是不需要告警,但无法通过编码去除时,可以通过不输出这类异常日志达到忽略告警的目的. 比如在系统中经常会出现断开的管道的相关问题,异常如下 org.apache.catalina.connector.ClientAbortException: java.i

  • .Net core Blazor+自定义日志提供器实现实时日志查看器的原理解析

    目录 场景 实现原理 如何使用? 1.启用blazor server(若你本来是,直接跳过) 2.安装咱的日志包:BXJG.BlazorServerLogger3.配置 自定义配置和样式 非微软的日志框架的集成 资源 基于blazor server的实时日志显示组件 场景 我们经常远程连接服务器去查看日志,比较麻烦,如果直接访问项目的某个页面就能实时查看日志就比较奈斯了,花了1天研究了下.net core 日志的原理,结合blazor实现了基本效果. 实现原理 自定义日志提供器,将日志记录到内存

  • java自定义日志输出文件(log4j日志文件输出多个自定义日志文件)

    log4j输出多个自定义日志文件 如果在实际应用中需要输出独立的日志文件,怎样才能把所需的内容从原有日志中分离,形成单独的日志文件呢? 先看一个常见的log4j.properties文件,它是在控制台和test.log文件中记录日志: 复制代码 代码如下: log4j.rootLogger=DEBUG, stdout, logfile log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layo

  • Flutter实战之自定义日志打印组件详解

    在Flutter中,如果我们需要打印日志,如果不进行自定义,我们只能使用自带的 print() 或者 debugPrint() 方法进行打印,但是这两种打印,日志都是默认 Info 层级的日志,很不友好,所以如果需要日志打印层级分明,我们就需要自定义一个日志打印组件,以下就来介绍如何自定义日志打印组件. 如何让输出的日志层级分明? 换种方式想,如果我们能在Flutter代码中,能够调用到原始Android中的Log组件,岂不是就能解决日志打印问题? 如何进行关联 在Flutter中,可以使用 M

  • 聊聊Unity 自定义日志保存的问题

    前言 之前unity5.x在代码中写了debug.log..等等,打包之后在当前程序文件夹下会有个对应的"outlog.txt",2017之后这个文件被移到C盘用户Appdata/LocalLow/公司名 文件夹下面.觉得不方便就自己写了个 代码 using UnityEngine; using System.IO; using System; using System.Diagnostics; using Debug = UnityEngine.Debug; public class

  • python实现自定义日志的具体方法

    1.导入logging模块: import logging 2.创建日志收集器: logger = logging.getLogger("日志收集器的name") 3.设置日志收集器的日志级别: logger.setLevel(logging.INFO) #设置收集器的级别为INFO. 4.给日志收集器创建输出渠道,根据第一部分的内容知:日志输出渠道包含控制台输出和文件输出. 5.设置日志输出的内容格式. # 设置日志的输出格式 fmt = "%(asctime)s %(na

随机推荐