如何使用logback以csv格式写入日志文件?

Kau*_*rty 7 java csv logback

我有一个要求,我需要使用 logback 以 csv 格式编写日志。我找到了一个样本,我可以做到这一点

    <appender name="csv" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>mylog.csv</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
    <!-- rollover daily -->
    <fileNamePattern>mylog-%d{yyyy-MM-dd}.%i.csv</fileNamePattern>
        <!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
        <maxFileSize>100MB</maxFileSize>    
        <maxHistory>60</maxHistory>
        <totalSizeCap>20GB</totalSizeCap>
        </rollingPolicy>
       <encoder>
         <pattern>%msg%n</pattern>
        </encoder>
     </appender>
Run Code Online (Sandbox Code Playgroud)

但是,我还需要在每个文件中都有一个这样的标准标题:-

    Time,User,Param1,Param2
Run Code Online (Sandbox Code Playgroud)

如何在每个滚动文件中添加标题

gly*_*ing 6

您可以实现自己的Layout,扩展 Logback 的PatternLayout

public class LogFileHeaderPatternLayout extends PatternLayout {

    private String header;

    public void setHeader(String header) {
        this.header = header;
    }

    @Override
    public String getFileHeader() {
        return header;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后像这样引用它:

<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
    <layout class="x.y.z.LogFileHeaderPatternLayout">
        <header>a,b,c,d</header>
        <pattern>%msg%n</pattern>
    </layout>
</encoder>
Run Code Online (Sandbox Code Playgroud)

如果 Logback 坚持在每次打开日志文件时(即每次应用程序启动时)都添加此标头,那么您可以getFileHeader()像这样进行条件化:

public String getFileHeader() {
    if (alreadyContainsHeader()) {
        return "";
    } else {
        return header;
    }
}

private boolean alreadyContainsHeader() {
    try(BufferedReader br = new BufferedReader(new FileReader(filePath))) {
        String line = null;
        while ((line = br.readLine()) != null) {
            if (line.contains(header)) {
                return true;
            } else {
                break;
            }
        }
    } catch (Exception ex) {
        ex.printStackTrace(System.err);
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

  • 'alreadyContainsHeader' 检查相当复杂,需要打开一个实时文件并读取其内容(第一行但仍然如此)。只检查文件是否存在并且不为空不是更好的解决方案吗? (3认同)
  • 谢谢。你得到了我的赞成!但是......你从哪里得到'filePath'(在 alreadyContainsHeader() 中) (2认同)