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数据中不要有逗号
相关推荐
程序员西西几秒前
SpringBoot接口安全:APIKey保护指南
java·spring boot·计算机·程序员·编程·编程开发
summer_west_fish19 分钟前
单体VS微服务:架构选择实战指南
java·微服务·架构
v***85721 分钟前
Ubuntu介绍、与centos的区别、基于VMware安装Ubuntu Server 22.04、配置远程连接、安装jdk+Tomcat
java·ubuntu·centos
烤麻辣烫28 分钟前
黑马程序员大事件后端概览(表现效果升级版)
java·开发语言·学习·spring·intellij-idea
q***965831 分钟前
Spring总结(上)
java·spring·rpc
思密吗喽33 分钟前
宠物商城系统
java·开发语言·vue·毕业设计·springboot·课程设计·宠物
大云计算机毕设42 分钟前
2026年计算机专业毕业设计热门选题推荐(微信小程序、Spring Boot、Python、大数据)
spring boot·毕业设计·课程设计·论文笔记·毕设
ss2731 小时前
019:深入解析可重入互斥锁:原理、实现与线程安全实践
java·数据库·redis
luyun0202021 小时前
牛批了,某音录播神器
java·windows·figma
高级程序源1 小时前
springboot社区医疗中心预约挂号平台app-计算机毕业设计源码16750
java·vue.js·spring boot·mysql·spring·maven·mybatis