【问题标题】:How to stack up log messages and log them just when an exception occurs?如何堆叠日志消息并在发生异常时记录它们?
【发布时间】:2018-04-11 18:07:50
【问题描述】:

我有一个执行一堆 SQL 命令的业务流程。我想将这些sql命令“堆叠”在一个堆栈中,并在发生异常时将它们写入DB,让我用一些代码解释一下

public void BusinessMethod()
{
    Log.Initialize(); // Clear the stack
    try
    {  
        Method1ThatExecutesSomeSQLs();
        Method2ThatExecutesSomeSQLs();
        Method3ThatExecutesSomeSQLs();
    }
    catch(Expection ex)
    {
        // if some exception occured in any Method above, them i write the log, otherwise, i dont want to log anything
        Log.Write();
    }
} 

//Example of some Method that executes SQL's
public void Method1ThatExecutesSomeSQLs()
{
    string sql = "select * from table";
    ExecuteSQL(sql);
    Log.StackUp("The following sql command was executed: " + sql); //Just stack up, dont write!
}

有谁知道 Log4Net 或 NLog 是否支持这种情况?如果没有,如何实现?

【问题讨论】:

  • 这可能无济于事(因为它不是 Log4Net),但我建议使用具有您描述的功能的 NLog 而不是 Log4Net。
  • @Michael 你能指出描述这个功能的 NLog 页面吗?
  • 嗯...我会,但我找不到它:( 不记得细节,很久以前了。但它的工作原理是这样的:你指定一个级别作为过滤条件,可以说错误。如果日志消息低于指定条件,则消息将被排队。如果级别等于或高于指定级别,则排队的消息和触发消息被记录。可能是缓冲和的组合过滤目标,但我找不到示例。我很确定我没有编写自定义代码来执行此操作...也许 SO 上的其他人可以提供示例...?

标签: c# logging log4net nlog


【解决方案1】:

NLog 4.5 支持开箱即用的场景。这将在发生警告/错误/致命时显示最后 50 条消息(导致触发自动刷新):

<target name="consoleWarn" xsi:type="AutoFlushWrapper" condition="level >= LogLevel.Warn" >
        <target xsi:type="BufferingWrapper" overflowAction="Discard" bufferSize="50">
             <target xsi:type="Console" layout="${level}:${message}" />
        </target>
</target>

NLog 4.4(和更早版本)需要更多帮助,因为 BufferingWrapper 没有溢出操作。相反,AsyncWrapper 可能会被滥用:

<target name="consoleWarn" xsi:type="AutoFlushWrapper" condition="level >= LogLevel.Warn" >
        <target xsi:type="BufferingWrapper" bufferSize="500">
             <target xsi:type="AsyncWrapper" queueLimit="50" overflowAction="Discard" fullBatchSizeWriteLimit="1" timeToSleepBetweenBatches="2000000000">
                <target xsi:type="Console" layout="${level}:${message}" />
             </target>
        </target>
</target>

另见https://github.com/NLog/NLog.Extensions.Logging/issues/127

【讨论】:

    【解决方案2】:

    我解决了在 MemoryTarget 中堆叠消息日志然后在需要时保存(刷新)的问题。看:

    public class Program
    {
        private static Logger logger = LogManager.GetCurrentClassLogger();
    
        static void Main(string[] args)
        {
            try
            {
                logger.Log(LogLevel.Error, "Start of the process");
                // Inside Business class i have a lot of other logger.log() calls
                // Inside the business class a have a lot of DAOs that calls logger.log()
                // In ither words, all the calls to logger.log() will be stacked up
                Business b = new Business();
                b.DoSomethig();
                logger.Debug("End of the Process.");
            }
            catch (Exception )
            {
                var target = (MemoryTarget)LogManager.Configuration.FindTargetByName("MemoTarget");
                var logs = target.Logs;
    
                // Get all the logs in the "stack" of log messages
                foreach (string s in target.Logs)
                {
                    Console.Write("logged: {0}", s);
                }
            }
    
        }
    }
    

    nlog.config:

    <targets>
        <target xsi:type="Memory" name="MemoTarget" layout="${date:format=dd-MM-yyyy HH\:mm\:ss} | ${callsite} | ${message}" />
     ...
    </targets>
    ...
    <rules>
        <logger name="*" minlevel="Debug" writeTo="MemoTarget" />
    </rules>
    ....
    

    运行后输出如下:

    logged: 30-10-2017 20:12:36 | NLog_Tests.Program.Main | Start of the process 
    logged: 30-10-2017 20:12:36 | NLog_Tests.Business.DoSomethig | Some business rule was executed
    logged: 30-10-2017 20:12:36 | NLog_Tests.DAOClass.ExecuteCommand | some sql was executed
    logged: 30-10-2017 20:12:36 | NLog_Tests.Program.Main | End of the Process.
    

    【讨论】:

    • 在此处添加 nlog.config 会很好:)
    • @Julian 我添加了 nlog.config
    【解决方案3】:

    有点晚了,但这是我的(减少的)配置:

    <?xml version="1.0" encoding="utf-8" ?>
    <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <targets async="true">
        <wrapper-target xsi:type="BufferingWrapper" name="buffer" bufferSize="32" flushTimeout="100">
          <wrapper-target xsi:type="PostFilteringWrapper">
            <defaultFilter>level >= LogLevel.Warn</defaultFilter>
            <when exists="level >= LogLevel.Error" filter="level >= LogLevel.Trace" />
            <target xsi:type="ColoredConsole" />
          </wrapper-target>
        </wrapper-target>
      </targets>
      <rules>
        <logger name="*" minlevel="Trace" writeTo="buffer" />
      </rules>
    </nlog>
    

    这会将低于警告级别的所有消息 (max=32) 排队。如果将记录大于或等于错误的消息,则将刷新队列。

    具有上述配置的 C# 测试代码。只有警告消息可见。如果添加了错误或致命消息,则所有消息都将可见。

    LogManager.Configuration = new XmlLoggingConfiguration(@"cfg\NLog.xml", false);
    LogManager.ReconfigExistingLoggers();
    
    LOG.Trace("trace");
    LOG.Debug("debug");
    LOG.Info("info");
    LOG.Warn("warn");
    //LOG.Error("error");
    //LOG.Fatal("fatal");
    
    LogManager.Flush();
    LogManager.Shutdown();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-12
      • 1970-01-01
      • 1970-01-01
      • 2011-10-23
      相关资源
      最近更新 更多