Как записать сообщение, когда BufferingForwardingAppender сброшен?

У меня есть BufferingForwardingAppender настроен на пересылку последних 10 сообщений на RollingFileAppender при появлении ERROR. Могу ли я сделать так, чтобы пользовательское сообщение отображалось в журнале перед каждой партией сообщений?

Я хочу указать, что это новое ERROR событие и его контекст, чтобы журнал можно было читать?

Моя конфигурация log4net выглядит примерно так:

<appender name="ErrorBufferingAppender" type="log4net.Appender.BufferingForwardingAppender">
  <bufferSize value="10" />
  <lossy value="true" />
  <evaluator type="log4net.Core.LevelEvaluator">
    <threshold value="ERROR" />
  </evaluator>
  <appender-ref ref="ErrorFileAppender" />
</appender>

<appender name="ErrorFileAppender" type="log4net.Appender.RollingFileAppender">
  <param name="File" value="logs\Errors.txt"/>
  <!-- other important parameters -->
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%-4thread] %-5level %logger{1} - %message%newline"/>
  </layout>
</appender>

И мой желаемый результат примерно такой

---------- ERROR ----------
2011-05-09 16:59:12,327 [8   ] INFO  AppLogger - DiskStorageMonitor.StartMonitoring()
2011-05-09 16:59:12,331 [8   ] INFO  AppLogger - DiskStorageMonitor.Initializing File System Watcher...
2011-05-09 16:59:12,341 [8   ] INFO  AppLogger - DiskStorageMonitor - LocalSlideDataStorageDrive: C:
2011-05-09 16:59:12,370 [8   ] INFO  AppLogger - Transition: From 'MinimumDiskSpaceQuotaState' to 'IdleState'.
2011-05-09 16:59:26,697 [8   ] INFO  AppLogger - Transition: From 'IdleState' to 'SlideHolderMacroState'.
2011-05-09 16:59:26,702 [8   ] INFO  AppLogger - Transition: From 'SlideHolderMacroState' to 'WaitingForMacroCmdResponseState'.
2011-05-09 16:59:26,781 [12  ] INFO  YStageManager - Moving to: -1.25
2011-05-09 16:59:26,782 [14  ] INFO  XStageManager - Moving to: -142
2011-05-09 16:59:30,800 [12  ] ERROR RecoveringErrorHandler - An error occurred. Retrying... (snipped exception message & stacktrace)

---------- ERROR ----------
2011-05-09 16:59:30,808 [12  ] WARN  MacroCameraRecoverySteps - An error occurred while calling the macro camera. Resetting and retrying...
2011-05-09 16:59:30,809 [12  ] INFO  MacroCameraManager - Resetting the Macro Camera.
2011-05-09 16:59:30,886 [12  ] ERROR GetMacroImageCommandHandler - Macro image processing failed for the slide in position 0. (snipped exception message & stacktrace)

person Anthony Mastrean    schedule 09.05.2011    source источник


Ответы (2)


У меня есть решение, которое, вероятно, сработает для вас, но это небольшой обходной путь. По сути, установите два приложения для записи в один и тот же файл. Когда вы записываете ошибку (которая запускает очистку буфера в вашем файле журнала), попросите другой приложение сначала записать текст «------- Ошибка --------» с новой строкой перед текст.

Вам придется немного поэкспериментировать с этим, чтобы заставить его работать, но это должно быть работоспособное решение. Apache позволяет нескольким приложениям записывать в один и тот же файл. Просто убедитесь, что вы установили + MinimalLock в свои приложения, чтобы они не блокировали файл. Вот ссылка SO, которая объясняет, как два приложения могут писать в один и тот же файл:

Может ли Log4net иметь несколько приложений для записи в один и тот же файл? < / а>

person IAmTimCorey    schedule 11.05.2011
comment
Звучит хорошо, я пытаюсь придумать, как это сделать без двух экземпляров регистратора в каждом классе, который мог бы написать сообщение об ошибке. - person Anthony Mastrean; 13.05.2011
comment
@Anthony Mastrean - вам не понадобятся два экземпляра в каждом классе, только два приложения. Второй будет реагировать только на события ERROR. Я что-то упускаю? - person IAmTimCorey; 13.05.2011
comment
Я не понимаю, как второе приложение волшебным образом запишет --- Ошибка --- в журнал без сообщения ... вы говорите, что Layout будет просто строкой, а не шаблоном% сообщения? - person Anthony Mastrean; 13.05.2011
comment
@Anthony Mastrean - вы должны создать второй аппендер, который будет обрабатывать событие ERROR. Таким образом, при возникновении ошибки запускаются оба приложения. Новый будет иметь шаблон, который просто записывает ---- Ошибка ---- и новую строку в текстовый файл, тогда ваш исходный модуль буферизации запускает запись в тот же файл журнала. С помощью одной команды журнала в коде вы можете запускать столько приложений, сколько захотите. - person IAmTimCorey; 13.05.2011
comment
У меня проблемы с подавлением печати исключения из сообщения ... Я получаю ----- ОШИБКА ----- ‹exception›: message ‹stacktrace› - person Anthony Mastrean; 13.05.2011

Благодаря BiggsTRC за отличные ответы. Это моя рабочая конфигурация log4net и пример вывода.

Это приложение отвечает на любое ERROR сообщение, записывая контекстный «заголовок» в журнал. Журнал минимально заблокирован, чтобы позволить этому и приложению буферизации записывать в файл. Тег ignoresException, установленный в false, фактически сообщает log4net, что этот макет запишет исключение (а не автоматически под сообщением). Но на самом деле я этого не хочу, это будет в другом приложении.

<appender name="ErrorSectionAppender" type="log4net.Appender.FileAppender">
  <filter type="log4net.Filter.LevelMatchFilter">
    <levelToMatch value="ERROR" />
  </filter>
  <filter type="log4net.Filter.DenyAllFilter" />
  <file value="logs\Errors.txt" />
  <appendToFile value="true" />
  <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
  <layout type="log4net.Layout.PatternLayout">
    <ignoresException value="false" />
    <conversionPattern value="%newline---------- ERROR @ %date ----------%newline" />
  </layout>
</appender>

Этот аппендер буферизует все сообщения до появления сообщения ERROR, затем выгружает последние 10 (bufferSize) сообщений и сообщение об ошибке в ErrorFileAppender.

<appender name="ErrorBufferingAppender" type="log4net.Appender.BufferingForwardingAppender">
  <bufferSize value="10" />
  <lossy value="true" />
  <evaluator type="log4net.Core.LevelEvaluator">
    <threshold value="ERROR" />
  </evaluator>
  <appender-ref ref="ErrorFileAppender" />
</appender>

Это собственно приложение с ошибкой. Схема преобразования стандартная. Обратите внимание на минимальную блокировку файла.

<appender name="ErrorFileAppender" type="log4net.Appender.RollingFileAppender">
  <file value="logs\Errors.txt"/>
  <appendToFile value="true"/>
  <staticLogFileName value="true"/>
  <rollingStyle value="Size"/>
  <maxFileSize value="1048576"/>
  <maxSizeRollBackups value="-1"/>
  <countDirection value="1"/>
  <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%date [%-4thread] %-5level %logger{1} - %message%newline"/>
  </layout>
</appender>

Вывод этих приложений выглядит следующим образом

---------- ERROR @ 2011-05-13 13:51:22,632 ----------
2011-05-13 13:51:04,937 [9   ] INFO  OmnyxScannerLogger - Transition: From 'No State' to 'CommunicationSyncState'.
2011-05-13 13:51:05,363 [12  ] DEBUG IMacroImageProcessor - hello, 10
2011-05-13 13:51:05,369 [19  ] INFO  XStageManager - Connecting
2011-05-13 13:51:05,369 [12  ] INFO  ZStageManager - Connecting
2011-05-13 13:51:05,369 [16  ] INFO  YStageManager - Connecting
2011-05-13 13:51:05,393 [9   ] INFO  OmnyxScannerLogger - Transition: From 'CommunicationSyncState' to 'SystemInitializeState'.
2011-05-13 13:51:08,528 [17  ] INFO  YStageManager - Homing
2011-05-13 13:51:08,539 [12  ] INFO  ZStageManager - Homing
2011-05-13 13:51:22,632 [14  ] ERROR RecoveringErrorHandler - An error occurred. Retrying...
Omnyx.Scanner.CliContracts.ScannerException: Injected: The stage failed to home.
   at Omnyx.Scanner.Simulation.ErrorInjection.ErrorInjectionInterceptor.Intercept(IInvocation invocation) in D:\Simulation\ErrorInjection\ErrorInjectionInterceptor.cs:line 42
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.IXStageManagerProxy.Home()

---------- ERROR @ 2011-05-13 13:51:33,758 ----------
2011-05-13 13:51:29,034 [9   ] INFO  OmnyxScannerLogger - DiskStorageMonitor.StartMonitoring()
2011-05-13 13:51:29,037 [9   ] INFO  OmnyxScannerLogger - DiskStorageMonitor.Initializing File System Watcher...
2011-05-13 13:51:29,046 [9   ] INFO  OmnyxScannerLogger - DiskStorageMonitor - LocalSlideDataStorageDrive: C:
2011-05-13 13:51:29,062 [9   ] INFO  OmnyxScannerLogger - -- LocalSlideDataStorageOverhead: 0
2011-05-13 13:51:29,075 [9   ] INFO  OmnyxScannerLogger - Transition: From 'MinimumDiskSpaceQuotaState' to 'IdleState'.
2011-05-13 13:51:31,727 [9   ] INFO  OmnyxScannerLogger - Transition: From 'IdleState' to 'SlideHolderMacroState'.
2011-05-13 13:51:31,732 [9   ] INFO  OmnyxScannerLogger - Transition: From 'SlideHolderMacroState' to 'WaitingForMacroCmdResponseState'.
2011-05-13 13:51:31,792 [12  ] INFO  YStageManager - Moving to: -1.25
2011-05-13 13:51:31,793 [20  ] INFO  XStageManager - Moving to: -142
2011-05-13 13:51:33,758 [12  ] ERROR RecoveringErrorHandler - An error occurred. Retrying...
Omnyx.Scanner.CliContracts.ScannerException: Injected: The macro camera failed.
   at Omnyx.Scanner.Simulation.ErrorInjection.ErrorInjectionInterceptor.Intercept(IInvocation invocation) in D:\Simulation\ErrorInjection\ErrorInjectionInterceptor.cs:line 42
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.IMacroCameraManagerProxy.TakeTopLitAndBackLitPictures()
person Anthony Mastrean    schedule 13.05.2011
comment
Ах, ManagerProxies ... приятно ;-) - person wexman; 09.06.2015
comment
@anthony: Где ErrorSectionAppender's appender-ref? - person eyal; 18.11.2015
comment
@eyal, насколько я помню ... ему не нужна ссылка, потому что он пишет в журнал напрямую. Добавители буферизации и пересылки обычно имеют ссылки. - person Anthony Mastrean; 19.11.2015
comment
@AnthonyMastrean Я этого не знал! Думаю, я не использовал FileAppender, поэтому мне всегда приходилось обновлять Rolling и Buffering, которые я использовал. Спасибо. - person eyal; 19.11.2015