logback 将日志保存CSV文件

背景

公司业务,要将数据要做本地备份记录,开始直接保存json格式,但是太占用存储,所以使用csv格式保存。

思路

1、使用csvWriter ,数据来时,将数据写入本地

不足:

如果每次数据来临时,创建一个csvWriter性能有影响,批量写入也可以,这不是主要原因。主要原因是,需要考虑什么时候创建csv文件,什么时候关闭csv流,当项目升级时,也要关闭流。注意的点太多(放弃)

2、csv其实就是一个文本,每行数据就是用逗号分割,我们可以将数据逗号分割好,直接使用info(data)来记录数据。

难点是,如何将标头写入文件。

自定义Appender、Encoder

xml文件

xml 复制代码
<appender name="USER_LOG" class="com.sjy.logback.CsvRollingFileAppender">
        <encoder class="com.sjy.logback.CsvPatternLayoutEncoder">
            <fileHeader>time,data,user,url</fileHeader>
            <charset>UTF-8</charset>
            <pattern>%msg%n</pattern>
        </encoder>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>/var/log/user-data.%d{yyyy-MM-dd}.csv</FileNamePattern>
            <MaxHistory>7</MaxHistory>
        </rollingPolicy>
    </appender>
<logger name="userLogger" level="INFO" additivity="false">
        <appender-ref ref="USER_LOG" />
    </logger>

CsvRollingFileAppender.java

java 复制代码
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.encoder.Encoder;
import ch.qos.logback.core.recovery.ResilientFileOutputStream;
import ch.qos.logback.core.rolling.RollingFileAppender;
import ch.qos.logback.core.util.FileUtil;

import java.io.File;
import java.io.IOException;

/*
判断文件是否存在,如果存在,将header 去除,如果不存在添加fileHeader
 */
public class CsvRollingFileAppender<E> extends RollingFileAppender<E> {
    @Override
    public void openFile(String file_name) throws IOException {
        lock.lock();
        try {
            File file = new File(file_name);
            boolean result = FileUtil.createMissingParentDirectories(file);
            if (!result) {
                addError("Failed to create parent directories for [" + file.getAbsolutePath() + "]");
            }

            ResilientFileOutputStream resilientFos = new ResilientFileOutputStream(file, append, FileAppender.DEFAULT_BUFFER_SIZE);
            resilientFos.setContext(context);
            CsvPatternLayoutEncoder encoder = (CsvPatternLayoutEncoder) this.getEncoder();
            String fileHeader = null;
            // 文件是否存在
            boolean isNew = !file.exists() || file.length() <= 0;
            if (!isNew) {
                // 设置null
                fileHeader = encoder.getFileHeader();
                encoder.setPatternLayoutFileHeader(null);
            }
            // 写入文件
            setOutputStream(resilientFos);
            if (!isNew) {
                encoder.setPatternLayoutFileHeader(fileHeader);
            }
        } finally {
            lock.unlock();
        }
    }
}

CsvPatternLayoutEncoder .java

java 复制代码
import ch.qos.logback.classic.PatternLayout;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.pattern.PatternLayoutEncoderBase;

public class CsvPatternLayoutEncoder extends PatternLayoutEncoderBase<ILoggingEvent> {
    private String fileHeader;
    private PatternLayout patternLayout;
    @Override
    public void start() {
        patternLayout = new PatternLayout();
        patternLayout.setContext(context);
        patternLayout.setPattern(getPattern());
        patternLayout.setFileHeader(getFileHeader());
        patternLayout.setOutputPatternAsHeader(outputPatternAsHeader);
        patternLayout.start();
        this.layout = patternLayout;
        super.start();
    }

    public String getFileHeader() {
        return fileHeader;
    }

    public void setFileHeader(String fileHeader) {
        this.fileHeader = fileHeader;
    }

    public void setPatternLayoutFileHeader(String fileHeader) {
        patternLayout.setFileHeader(fileHeader);
    }
}
java 复制代码
private static Logger log = LoggerFactory.getLogger("userLogger");
// 写入文件
public void logToFile() {
    log.info(time+","+data+","+user+","+url);
}

注意事项

  1. 因为CSV是一个用逗号分割的文本,所以在datauser数据中不要有逗号
相关推荐
qq_2518364572 分钟前
基于springboot vue3 在线考试系统设计与实现 源码数据库 文档
数据库·spring boot·后端
哎呀呀嗯呀呀19 分钟前
class 031 位运算的骚操作
java·算法·位运算
2401_8581205322 分钟前
古典舞在线交流平台:SpringBoot设计与实现详解
java·spring boot·后端
大白飞飞30 分钟前
IDEA创建、导入、删除maven项目
java·maven·intellij-idea
赐你岁月如歌35 分钟前
如何使用ssm实现基于web的网站的设计与实现+vue
java·后端·ssm
2401_857297911 小时前
秋招内推2025-招联金融
java·前端·算法·金融·求职招聘
一 乐1 小时前
考研论坛平台|考研论坛小程序系统|基于java和微信小程序的考研论坛平台小程序设计与实现(源码+数据库+文档)
java·数据库·学习·考研·微信·小程序·源码
一 乐1 小时前
租拼车平台|小区租拼车管理|基于java的小区租拼车管理信息系统小程序设计与实现(源码+数据库+文档)
java·数据库·vue.js·微信·notepad++·拼车
xmh-sxh-13142 小时前
如何选择数据库架构
java
jxxchallenger2 小时前
踩坑spring cloud gateway /actuator/gateway/refresh不生效
java·数据库·gateway