2

我有一个通用的日志项目,它使用 log4net 来记录日志事件。由于它是一个普通项目,它以非标准方式配置:几乎所有内容都是通过 C# 代码设置的。

现在,我以这种方式配置了一个 AdoNet 附加程序,其中包括记录触发日志事件的方法。它是作为日志初始化的一部分创建的,定义如下:

appender.AddParameter(new AdoNetAppenderParameter()
{
    ParameterName = "@Method",
    DbType = DbType.String,
    Size = 255,
    Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%method")) as IRawLayout
});

由于我绑定了 log4net%method属性,这将自动提取触发日志事件的方法名称,并将其发送到数据库中的一个名为的参数中,该参数@Method最终将插入到具有名为 .的列的数据库表中Method

但是,我正在添加一些新功能来全局处理异常并记录它们。当一个异常从任何地方冒泡到调用堆栈的顶部时,它将被传递给这个新的全局方法,以便记录它。我可以访问异常,所以我可以看到导致此异常的控制器和方法。我可以轻松地将其添加为 log4net 自定义属性(映射到类似的东西%property{ExceptionMethod})。我的问题是用我自己的自定义属性覆盖(或覆盖)log4net 的%method属性。

那么,如何让 log4net 有条件地在%method通过%property{ExceptionMethod}AdoNet 附加程序发送数据以在我的日志记录数据库表的“方法”列下记录此信息时进行选择?这甚至可行吗?

4

2 回答 2

2

在不确切知道您如何配置和使用 log4net 的情况下,很难编写适合您现有框架的代码:此示例创建了两个附加程序,一个使用%method,一个使用%property{ExceptionMethod},并将它们分配给不同的记录器:

public abstract class BaseAppender : AdoNetAppender
{
    protected BaseAppender()
    {
        // Add common parameters, set connection strings etc

        // e.g.
        this.AddParameter(new AdoNetAppenderParameter
        {
            ParameterName = "@log_level",
            DbType = DbType.String,
            Size = 50,
            Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%level")) as IRawLayout
        });

        // Then ask each subclass to add the extra parameters
        this.AddExtraParameters();
    }

    protected abstract void AddExtraParameters();
}

public class RuntimeAppender : BaseAppender
{
    protected override void AddExtraParameters()
    {
        this.AddParameter(new AdoNetAppenderParameter
        {
            ParameterName = "@Method",
            DbType = DbType.String,
            Size = 255,
            Layout = new RawLayoutConverter().ConvertFrom(new PatternLayout("%method")) as IRawLayout
        });
    }
}

public class UnhandledExceptionAppender : BaseAppender
{
    protected override void AddExtraParameters()
    {
        this.AddParameter(new AdoNetAppenderParameter
        {
            ParameterName = "@Method",
            DbType = DbType.String,
            Size = 255,
            Layout =
                new RawLayoutConverter().ConvertFrom(new PatternLayout("%property{ExceptionMethod}")) as IRawLayout
        });
    }
}

public sealed class RuntimeLogger : Logger
{
    public RuntimeLogger(string name)
        : base(name)
    {
        this.Appenders.Add(new RuntimeAppender());
        this.Level = Level.Error; // etc
    }
}

public sealed class UnhandledExceptionLogger : Logger
{
    public UnhandledExceptionLogger(string name)
        : base(name)
    {
        this.Appenders.Add(new UnhandledExceptionAppender());
        this.Level = Level.Error; // etc
    }
}

然后,在运行时,您选择使用哪个:

public class ExceptionHandler
{
    public void HandleException(Exception ex)
    {
        string exceptionMethod = "set exception method here" ; 
        GlobalContext.Properties["ExceptionMethod"] = exceptionMethod;

        var logger = new UnhandledExceptionLogger("Logger Name Goes Here");
        logger.Log(Level.Error, "Message", ex);
    }
}

public class RuntimeLogging
{
    public void LogSomething(Exception ex)
    {
        var logger = new RuntimeLogger("Logger Name Goes Here");
        logger.Log(Level.Error, "Message", ex);
    }
}   
于 2015-02-24T13:07:22.073 回答
0

根据您的需要,您可能会发现AdoNetAppender完全在代码中实现更容易。

至少有一种方法可以做到这一点,在我之前的答案中找到

于 2015-02-24T01:46:08.307 回答