Log4net - динамическое переключение приложения между AdoNetAppender и RollingFileAppender

Я использую AdoNetAppender (сервер SQL) в своем приложении asp.net и хотел бы использовать RollingFileAppender в случае возникновения каких-либо проблем с подключением к SQL. Есть ли способ настроить использование RollingFileAppender только при возникновении проблемы с AdoNetAppender?

Спасибо

пор


person porhills    schedule 07.05.2009    source источник


Ответы (2)


В log4net нет встроенной поддержки такого сценария аварийного переключения, проблема заключается в том, что приложения достаточно изолированы друг от друга в архитектуре log4net.

Обычная установка, однако, состоит в том, чтобы оба приложения регистрировались параллельно, только тогда, когда файл-приложение хранит, скажем, данные за несколько недель. Если AdoNetAppender выйдет из строя, у вас всегда будут самые свежие данные в файлах.

Но я определенно вижу здесь случай для приложения, которое может иметь список приоритетов вложенных приложений, выполняющих простую отработку отказа в случае сбоя. Это не должно быть слишком сложно реализовать на основе AppenderSkeleton < / а>.

person Peter Lillevold    schedule 08.05.2009
comment
Спасибо, Питер, за ваше драгоценное время и прекрасные объяснения. Я посмотрю на AppenderSkeletton. - person porhills; 08.05.2009

Я реализовал такое приложение и написал об этом здесь и здесь (зеркало). Код можно найти здесь.

Я расширил AppenderSkeleton и создал новый Appender под названием FailoverAppender, который имеет два члена типа AppenderSkeleton.

  • Приложение по умолчанию под названием «PrimaryAppender» - используется по умолчанию, пока оно не выйдет из строя.
  • Приложение аварийного переключения под названием «FailoverAppender» - используется только после сбоя основного.

Фактический тип PrimaryAppender и FailoverAppender настраивается с использованием синтаксиса конфигурации log4net xml (см. Пример ниже).

Фрагмент:

public class FailoverAppender : AppenderSkeleton
{
    private AppenderSkeleton _primaryAppender;
    private AppenderSkeleton _failOverAppender;
     ....
}

В реализации метода Append я отправляю по умолчанию LoggingEvents только в PrimaryAppender и заключите его в try-catch. Если PrimaryAppender выбрасывает (терпит неудачу), я сигнализирую флагу и отправляю LoggingEvent в FailoverAppender. Следующие события LoggingEvents будут отправлены напрямую и только в FailoverAppender.

protected override void Append(LoggingEvent loggingEvent)
{
    if (LogToFailOverAppender)
    {
        _failOverAppender?.DoAppend(loggingEvent);
    }
    else
    {
        try
        {
            _primaryAppender?.DoAppend(loggingEvent);
        }
        catch
        {
            ActivateFailOverMode();
            Append(loggingEvent);
        }
    }
}

Кроме того, я создал собственный ErrorHandler, который будет распространять исключения внутреннего приложения, чтобы сигнализировать о внутреннем сбое приложения, что позволит отправлять события LoggingEvents только в FailoverAppender.

class FailOverErrorHandler : IErrorHandler
{
    public FailOverAppender FailOverAppender { get; set; }

    public FailOverErrorHandler(FailOverAppender failOverAppender)
    {
        FailOverAppender = failOverAppender;
    }

    public void Error(string message, Exception e, ErrorCode errorCode)
        => FailOverAppender.ActivateFailOverMode();

    public void Error(string message, Exception e)
        => FailOverAppender.ActivateFailOverMode();

    public void Error(string message)
        => FailOverAppender.ActivateFailOverMode();
}

Пример конфигурации:

<!--This custom appender handles failovers. If the first appender fails, it'll delegate the message to the back appender-->
<appender name="FailoverAppender" type="MoreAppenders.FailoverAppender">
    <layout type="log4net.Layout.PatternLayout">
        <conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
    </layout>

    <!--This is a custom test appender that will always throw an exception -->
    <!--The first and the default appender that will be used.-->
    <PrimaryAppender type="MoreAppenders.ExceptionThrowerAppender" >
        <ThrowExceptionForCount value="1" />
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
        </layout>        
    </PrimaryAppender>

    <!--This appender will be used only if the PrimaryAppender has failed-->
    <FailOverAppender type="log4net.Appender.RollingFileAppender">
        <file value="log.txt"/>
        <rollingStyle value="Size"/>
        <maxSizeRollBackups value="10"/>
        <maximumFileSize value="100mb"/>
        <appendToFile value="true"/>
        <staticLogFileName value="true"/>
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5level %logger - %message%newline"/>
        </layout>
    </FailOverAppender>
</appender>
person m1o2    schedule 14.02.2019