Подтвердить что ты не робот

Как свернуть файл журнала при запуске в журнале

Я хотел бы настроить logback, чтобы сделать следующее.

  • Вход в файл
  • Загрузите файл, когда он достигнет 50 МБ.
  • Сохранять журналы на 7 дней
  • При запуске всегда создайте новый файл (сделайте рулон)

У меня все работает, за исключением последнего элемента, рулона запуска. Кто-нибудь знает, как это достичь? Здесь config...

  <appender name="File" class="ch.qos.logback.core.rolling.RollingFileAppender">

    <layout class="ch.qos.logback.classic.PatternLayout">
      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg \(%file:%line\)%n</Pattern>
    </layout>

    <File>server.log</File>

    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <FileNamePattern>server.%d{yyyy-MM-dd}.log</FileNamePattern>
      <!-- keep 7 days' worth of history -->
      <MaxHistory>7</MaxHistory>

      <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
        <MaxFileSize>50MB</MaxFileSize>
      </TimeBasedFileNamingAndTriggeringPolicy>

    </rollingPolicy>
  </appender>
4b9b3361

Ответ 1

Ни одно из других предложений не было подходящим для моей ситуации. Я не хотел использовать решение, основанное на размерах и времени, потому что для этого требуется настройка MaxFileSize, и мы используем строго временную политику. Вот как я завершил загрузку файла при запуске с помощью TimeBasedRollingPolicy:

@NoAutoStart
public class StartupTimeBasedTriggeringPolicy<E> 
        extends DefaultTimeBasedFileNamingAndTriggeringPolicy<E> {

    @Override
    public void start() {
        super.start();
        nextCheck = 0L;
        isTriggeringEvent(null, null);
        try {
            tbrp.rollover();
        } catch (RolloverFailure e) {
            //Do nothing
        }
    }

}

Хитрость заключается в том, чтобы установить значение nextCheck равным 0L, так что isTriggeringEvent() подумает, что пришло время перевернуть файл журнала. Таким образом, он выполнит код, необходимый для вычисления имени файла, а также удобный сброс значения nextCheck time. Последующий вызов rollover() вызывает сканирование файла журнала. Поскольку это происходит только при запуске, это более оптимальное решение, чем те, которые выполняют сравнение внутри isTriggerEvent(). Как бы мало ни было это сравнение, он все же несколько ухудшает производительность при каждом сообщении журнала. Это также приводит к тому, что опрокидывание происходит сразу при запуске, вместо ожидания первого события журнала.

Аннотации @NoAutoStart важны для предотвращения выполнения Joran метода start() до завершения всей другой инициализации. В противном случае вы получите исключение NullPointerException.

Вот конфигурация:

  <!-- Daily rollover appender that also appends timestamp and rolls over on startup -->
  <appender name="startupDailyRolloverAppender" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOG_FILE}</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <fileNamePattern>${LOG_FILE}.%d{yyyyMMdd}_%d{HHmmss,aux}</fileNamePattern>
      <TimeBasedFileNamingAndTriggeringPolicy class="my.package.StartupTimeBasedTriggeringPolicy" />
    </rollingPolicy>
    <encoder>
      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
  </appender> 

Надеюсь, это поможет!

Ответ 2

Он работает для меня, используя следующий класс как timeBasedFileNamingAndTriggeringPolicy:

import java.io.File;
import java.util.concurrent.atomic.AtomicBoolean;

import ch.qos.logback.core.joran.spi.NoAutoStart;
import ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP;

@NoAutoStart
public class Trigger<E> extends SizeAndTimeBasedFNATP<E>
{
    private final AtomicBoolean trigger = new AtomicBoolean();

    public boolean isTriggeringEvent(final File activeFile, final E event) {
        if (trigger.compareAndSet(false, true) && activeFile.length() > 0) {
            String maxFileSize = getMaxFileSize();
            setMaxFileSize("1");
            super.isTriggeringEvent(activeFile, event);
            setMaxFileSize(maxFileSize);
            return true;
        }
        return super.isTriggeringEvent(activeFile, event);
    }
}

Ответ 3

Я нашел еще одно решение для каротажа logFile один раз, когда приложение запускается.

Я использую logback RollingFileAppender с logback FixedWindowRollingPolicy и свою собственную реализацию TriggeringPolicy<E>.

FixedWindowRollingPolicy получает файлNamePattern для нового logFile, где %1 - это новый номер файла. MaxIndex означает максимальное количество моей "истории". Дополнительная информация: FixedWindowRollingPolicy

Мои реализации TriggeringPolicy возвращает true для first, когда вызывается isTriggeringEvent (...). Таким образом, WindowRollingPolicy перекатывает лог файлы, когда политика вызывается в первый раз, а затем она не будет перевернуться снова.

xml-конфигурация для RollingFileAppender:

<configuration>
    ...
    <appender name="FILE_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>logFile.log</file>

        <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy">
            <fileNamePattern>logFile.%i.log</fileNamePattern>
            <minIndex>1</minIndex>
            <maxIndex>4</maxIndex>
        </rollingPolicy>

        <triggeringPolicy class="my.classpath.RollOncePerSessionTriggeringPolicy"/>
    </appender>
...
</configuration>

TriggeringPolicy:

package my.classpath;

import ch.qos.logback.core.rolling.TriggeringPolicyBase;

import java.io.File;

public class RollOncePerSessionTriggeringPolicy<E> extends TriggeringPolicyBase<E> {
    private static boolean doRolling = true;

    @Override
    public boolean isTriggeringEvent(File activeFile, E event) {
        // roll the first time when the event gets called
        if (doRolling) {
            doRolling = false;
            return true;
        }
        return false;
    }
}

Ответ 4

Переопределение метода isTriggeringEvent() в ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP должно работать хорошо. Просто верните "true" в первый раз, когда вызывается метод TriggeringEvent().

Ответ 5

Для решения с использованием уже существующих компонентов logback предлагает уникально названные файлы: http://logback.qos.ch/manual/appenders.html#uniquelyNamed

В течение фазы разработки приложения или в случае короткоживущих приложений, например. пакетных приложений, желательно создать новый файл журнала при каждом запуске нового приложения. Это довольно легко сделать с помощью элемента <timestamp>.

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <timestamp key="startTimestamp" datePattern="yyyyMMddHHmmssSSS"/>
    <appender name="File"
    class="ch.qos.logback.core.rolling.RollingFileAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg \(%file:%line\)%n</Pattern>
        </layout>

        <file>server-${startTimestamp}.log</file>

        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <FileNamePattern>server-${startTimestamp}-%d{yyyy-MM-dd}-%i.log</FileNamePattern>
            <!-- keep 7 days' worth of history -->
            <MaxHistory>7</MaxHistory>

            <TimeBasedFileNamingAndTriggeringPolicy
            class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <MaxFileSize>1KB</MaxFileSize>
            </TimeBasedFileNamingAndTriggeringPolicy>
        </rollingPolicy>
    </appender>
    <root level="DEBUG">
        <appender-ref ref="File" />
    </root>
</configuration>

ОБНОВЛЕНО для logback-1.2.1

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <timestamp key="startTimestamp" datePattern="yyyyMMddHHmmssSSS"/>
    <appender name="File"
    class="ch.qos.logback.core.rolling.RollingFileAppender">
        <layout class="ch.qos.logback.classic.PatternLayout">
            <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg \(%file:%line\)%n</Pattern>
        </layout>

        <file>server-${startTimestamp}.log</file>

        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <fileNamePattern>server-${startTimestamp}-%d{yyyy-MM-dd}-%i.log</fileNamePattern>
            <maxFileSize>10MB</maxFileSize>
            <!-- keep 7 days' worth of history -->
            <maxHistory>7</maxHistory>
            <totalSizeCap>20GB</totalSizeCap>
        </rollingPolicy>
    </appender>
    <root level="DEBUG">
        <appender-ref ref="File" />
    </root>
</configuration>

Ответ 6

Решение Ceki, по-видимому, не работает для меня, но, по-видимому, по крайней мере частично работает.

Он взорвется, потому что он не может видеть скользящую политику при запуске TimeBasedFileNamingAndTriggeringPolicyBase. С некоторой хакерской я получил его сделать некоторые регистрации, и с некоторыми более я получил его, чтобы наблюдать триггер, но затем он сломался снова, потому что он не мог решить одно из свойств файла... Пакет является logback один так я может попасть в некоторые из внутренних частей, чтобы воспроизвести некоторую логику в SizeAndTimeBasedFNATP#isTriggeringEvent и вызвать computeCurrentPeriodsHighestCounterValue. Я думаю, что что-то по этим линиям может работать, просто пока не нашли волшебную комбинацию. Я действительно надеюсь, что я делаю что-то глупое, потому что в противном случае я думаю, что это будет означать либо открытие некоторых деталей для подклассификации, либо включение этой прямой в журнал в качестве другой политики перехода/запуска.

logback.xml: выполнил различные упорядочения triggeringPolicy, TimeBasedFileNamingAndTriggeringPolicy внутри и вне rollingPolicy.

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOG_DIR}/${LOG_FILE_BASE}.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>${LOG_DIR}/${LOG_FILE_BASE}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
        <MaxHistory>7</MaxHistory>

        <TimeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.RollOnStartupPolicy" />
    </rollingPolicy>

    <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
        <level>INFO</level>
    </filter>

    <encoder>
        <pattern>%msg%n</pattern>
    </encoder>
</appender>

Политика запуска:

package ch.qos.logback.core.rolling;
public class RollOnStartupPolicy<E> extends SizeAndTimeBasedFNATP<E> {
private final AtomicBoolean firstTime = new AtomicBoolean(true);

    @Override
    public boolean isTriggeringEvent(File activeFile, E event) {
        if (!firstTime.get()) { // fast path
            return false;
        }

        if (firstTime.getAndSet(false)) {
            return true;
        }
        return false;
    }
}

Исключение:

java.lang.NullPointerException
at  at ch.qos.logback.core.rolling.TimeBasedFileNamingAndTriggeringPolicyBase.start(TimeBasedFileNamingAndTriggeringPolicyBase.java:46)
at  at ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP.start(SizeAndTimeBasedFNATP.java:36)
at  at ch.qos.logback.core.joran... [snip joran config]

Ответ 7

Создайте свой собственный подкласс ch.qos.logback.core.rolling.TimeBasedRollingPolicy и переопределите его start

public class MyPolicy
    extends ch.qos.logback.core.rolling.TimeBasedRollingPolicy
{

    public void start ( )
    {
        super.start( );
        rollover( );
    }
}

Ответ 8

У меня есть следующее, чтобы работать (сочетая идеи из предыдущих ответов). Примечание. Я имел дело с файлами на основе размера, а не по времени, но я предполагаю, что это же решение работает.

public class StartupSizeBasedTriggeringPolicy<E> extends ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy<E> {

private final AtomicReference<Boolean> isFirstTime = new AtomicReference<Boolean>(true);

@Override
public boolean isTriggeringEvent(final File activeFile, final E event) {

    //this method appears to have side-effects so always call
    boolean result = super.isTriggeringEvent(activeFile, event);

    return isFirstTime.compareAndSet(true, false) || result;
}

}

Ответ 9

Я наконец понял это. Я могу рулон по размеру, времени и запуску. Вот решение:

Создайте свой собственный класс

@NoAutoStart
public class StartupSizeTimeBasedTriggeringPolicy<E> extends SizeAndTimeBasedFNATP<E> {

    private boolean started = false;

    @Override
    public boolean isTriggeringEvent( File activeFile, E event ) {
        if ( !started ) {
            nextCheck = 0L;
            return started = true;
        }

        return super.isTriggeringEvent( activeFile, event );
    };
}

2nd configure logback

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOGS_DIR}/${FILE_NAME}.log</file>
    <encoder>
        <pattern>%d [%thread] %-5level %logger{50} - %msg%n</pattern>
    </encoder>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <fileNamePattern>${LOGS_DIR}/${FILE_NAME}.%d{yyyy-MM-dd}_%d{HHmmss,aux}.%i.log.zip</fileNamePattern>
        <maxHistory>30</maxHistory>
        <TimeBasedFileNamingAndTriggeringPolicy class="my.StartupSizeTimeBasedTriggeringPolicy">
            <MaxFileSize>250MB</MaxFileSize> 
        </TimeBasedFileNamingAndTriggeringPolicy>
    </rollingPolicy>
</appender>

Ответ 10

Это решение действительно работает, спасибо большое. Однако есть один раздражающий сбой: когда вы запускаете программу в первый раз, журнал запускается сразу после его создания, когда он пуст или почти пуст. Поэтому я предлагаю исправить: проверьте, существует ли файл журнала и не является пустым в момент вызова метода. Кроме того, еще одно косметическое исправление: переименуйте "начальную" переменную, поскольку она скрывает унаследованный элемент с тем же именем.

@NoAutoStart
public class StartupSizeTimeBasedTriggeringPolicy<E> extends     SizeAndTimeBasedFNATP<E> {

    private boolean policyStarted;

    @Override
    public boolean isTriggeringEvent(File activeFile, E event) {
        if (!policyStarted) {
            policyStarted = true;
            if (activeFile.exists() && activeFile.length() > 0) {
                nextCheck = 0L;
                return true;
            }
        }
        return super.isTriggeringEvent(activeFile, event);
    }
}

Кроме того, я считаю, что он работает правильно с версией журнала версии 1.1.4-SNAPSHOT (я получил исходный код и скомпилировал его сам), но он не полностью работает с выпуском версии 1.1.3. В 1.1.3 он правильно определяет файлы с указанным часовым поясом, но опрокидывание по-прежнему происходит в полночь по часовому поясу по умолчанию.

Ответ 11

API изменился (например, setMaxFileSize больше не существует), и многие из вышеперечисленных функций, похоже, не работают, но у меня есть что-то, что работает для меня против logback 1.1.8 (последнее в настоящее время).

Я хотел запуститься при запуске и рулонах по размеру, но не время. Это делает:

public class RollOnStartupAndSizeTriggeringPolicy<E> extends SizeBasedTriggeringPolicy<E> {
    private final AtomicBoolean firstTime = new AtomicBoolean();

    public boolean isTriggeringEvent(final File activeFile, final E event) {
        if (firstTime.compareAndSet(false, true) && activeFile != null && activeFile.length() > 0) {
            return true;
        }
        return super.isTriggeringEvent(activeFile, event);
    }
}

С этим вам также нужна скользящая политика. FixedWindowRollingPolicy, вероятно, сделает, но мне это не нравится, потому что я хочу хранить большое количество файлов, и для этого это очень неэффективно. Что-то, что число постепенно увеличивается (вместо того, чтобы скользить подобно FixedWindow), будет работать, но этого не существует. Пока я пишу сам, я решил использовать время вместо счета. Я хотел бы продлить текущий код регистрации, но для материала, основанного на времени, политики катания и запуска часто объединяются в один класс, и есть журналы вложенности и кругового материала и поля без геттеров, поэтому я нашел это довольно невозможным. Поэтому мне пришлось делать многое с нуля. Я поддерживаю его просто и не реализую такие функции, как сжатие - я бы хотел их использовать, но я просто пытаюсь сохранить его простым.

public class TimestampRollingPolicy<E> extends RollingPolicyBase {
    private final RenameUtil renameUtil = new RenameUtil();
    private String activeFileName;
    private String fileNamePatternStr;
    private FileNamePattern fileNamePattern;

    @Override
    public void start() {
        super.start();
        renameUtil.setContext(this.context);
        activeFileName = getParentsRawFileProperty();
        if (activeFileName == null || activeFileName.isEmpty()) {
            addError("No file set on appender");
        }
        if (fileNamePatternStr == null || fileNamePatternStr.isEmpty()) {
            addError("fileNamePattern not set");
            fileNamePattern = null;
        } else {
            fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context);
        }
        addInfo("Will use the pattern " + fileNamePattern + " to archive files");
    }

    @Override
    public void rollover() throws RolloverFailure {
        File f = new File(activeFileName);
        if (!f.exists()) {
            return;
        }
        if (f.length() <= 0) {
            return;
        }
        try {
            String archiveFileName = fileNamePattern.convert(new Date(f.lastModified()));
            renameUtil.rename(activeFileName, archiveFileName);
        } catch (RolloverFailure e) {
            throw e;
        } catch (Exception e) {
            throw new RolloverFailure(e.toString(), e);
        }
    }

    @Override
    public String getActiveFileName() {
        return activeFileName;
    }

    public void setFileNamePattern(String fnp) {
        fileNamePatternStr = fnp;
    }
}

И тогда config выглядит как

<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
  <encoder>
    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
  </encoder>
  <file>/tmp/monitor.log</file>
  <rollingPolicy class="my.log.TimestampRollingPolicy">
    <fileNamePattern>/tmp/monitor.%d{yyyyMMdd-HHmmss}.log</fileNamePattern>
  </rollingPolicy>
  <triggeringPolicy class="my.log.RollOnStartupAndSizeTriggeringPolicy">
    <maxFileSize>1gb</maxFileSize>
  </triggeringPolicy>
</appender>

Если вы расстроены, это не решено изначально, проголосуйте за него в

http://jira.qos.ch/browse/LOGBACK-204

http://jira.qos.ch/browse/LOGBACK-215

(это были годы, и для меня это абсолютно важная функциональность, хотя я знаю, что многие другие фреймворки тоже терпят неудачу)