如何按名称空间对 log4net 中的日志消息进行分组?

发布于 2024-10-27 23:00:31 字数 6136 浏览 3 评论 0原文

我正在尝试实现自己的 log4net 附加程序,它将按名称空间将消息分组。 问题是,我无法按照我的意愿让 log4net 记录位置信息。

  class Program
{
    protected static IWindsorContainer container;
    static void Main(string[] args)
    {
        container = new WindsorContainer();
        container.Kernel.Resolver.AddSubResolver(new ArrayResolver(container.Kernel));

        // add facilities
        container.AddFacility("logging.facility", new LoggingFacility(LoggerImplementation.Log4net, "log4net.config"));
        container.Register(Component.For<ParentClass>().ImplementedBy<ParentClass>());
        container.Register(Component.For<ChildClass>().ImplementedBy<ChildClass>());                      

        var parentClass = container.Resolve<ParentClass>();
        var childClass = container.Resolve<ChildClass>();
        parentClass.Init();
        childClass.Init();

    }
}

public class ParentClass
{
    private readonly ILogger logger;

    private ILog localLogger;

    public ParentClass(ILogger logger)
    {
        this.logger = logger;
        localLogger = LogManager.GetLogger(GetType());
        logger.Info("ctor ioc logger, type: {0}",GetType().Name);
        localLogger.Info(string.Format("ctor local logger, type: {0}", GetType().Name));
    }

    public void Init()
    {
        logger.Info("init ioc logger, type: {0}", GetType().Name);
        localLogger.Info(string.Format("init local logger, type: {0}", GetType().Name));
    }
}

public class ChildClass : ParentClass
{
    public ChildClass(ILogger logger) : base(logger)
    {

    }
}

输出的

2011-03-28 09:58:55 INFO 10 ParentClass - ctor ioc logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ParentClass - ctor local logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ParentClass - ctor ioc logger, type: ChildClass
2011-03-28 09:58:55 INFO 10 ParentClass - ctor local logger, type: ChildClass
2011-03-28 09:58:55 INFO 10 ParentClass - init ioc logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ParentClass - init local logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ParentClass - init ioc logger, type: ChildClass
2011-03-28 09:58:55 INFO 10 ParentClass - init local logger, type: ChildClass

问题是,log4net 类名始终输出为基类名(ParentClass)。我最初认为,这可能是温莎城堡,导致了这样的问题,但结果显示,即使我手动创建记录器实例,它仍然记录基类名称。可能有人知道,如何强制 log4net 写入实际实例类名?

更新

这里使用了 log4net 配置:

<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
  <file value="c:\temp\testlog.log" />
  <appendToFile value="true" />
  <maximumFileSize value="10MB" />
  <maxSizeRollBackups value="2" />

  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%utcdate{yyyy-MM-dd HH:mm:ss} %level %thread %C{1} - %message%newline" />
  </layout>
</appender>

<root>
  <level value="INFO" />
  <appender-ref ref="RollingFile" />      
</root>

上面的输出是我得到的,我期望得到的是:

2011-03-28 09:58:55 INFO 10 ParentClass - ctor ioc logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ParentClass - ctor local logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ChildClass - ctor ioc logger, type: ChildClass
2011-03-28 09:58:55 INFO 10 ChildClass - ctor local logger, type: ChildClass
2011-03-28 09:58:55 INFO 10 ParentClass - init ioc logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ParentClass - init local logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ChildClass - init ioc logger, type: ChildClass
2011-03-28 09:58:55 INFO 10 ChildClass - init local logger, type: ChildClass

更新 2

如果有人需要这样的东西,这里是工作附加器实现:

public class GroupStringListAppender : log4net.Appender.AppenderSkeleton
{
    private readonly int listLength = 30;
    private readonly Func<string, string> pathFuction;
    private readonly Dictionary<string, List<string>> messagesDictionary = new Dictionary<string, List<string>>();

    public GroupStringListAppender(int listLength, Func<string, string> pathFuction)
    {
        this.listLength = listLength;
        this.pathFuction = pathFuction;
    }

    public List<string> GetMessages(string path)
    {
        return messagesDictionary[path];
    }        

    protected override void Append(LoggingEvent loggingEvent)
    {
        var msg = loggingEvent.RenderedMessage;
        var path = pathFuction.Invoke(loggingEvent.LoggerName);

        if (!messagesDictionary.ContainsKey(path))
        {
            messagesDictionary.Add(path, new List<string>());
            OnNewPathCreated(path);
        }

        var list = messagesDictionary[path];        

        while (list.Count - listLength > 0)
        {
            list.RemoveAt(0);    
        }

        list.Add(msg);

        OnAppended(path, list);          
    }

    public event AppendedEventHandler Appended;

    public void OnAppended(string path, List<string> list)
    {
        AppendedEventHandler handler = Appended;
        if (handler != null) handler(this, new LoggerMessageAppendedEventArgs(path, list));
    }

    public event NewPathCreatedHandler NewPathCreated;

    public void OnNewPathCreated(string path)
    {
        var handler = NewPathCreated;
        if (handler != null) handler(this, new NewPathCreatedHandlerArgs(path));
    }
}

public delegate void NewPathCreatedHandler(object sender, NewPathCreatedHandlerArgs args);

public class NewPathCreatedHandlerArgs : EventArgs
{
    public string Path { get; set; }

    public NewPathCreatedHandlerArgs(string path)
    {
        Path = path;
    }
}

public class LoggerMessageAppendedEventArgs : EventArgs
{
    public string Path { get; set; }
    public List<string> List { get; set; }

    public LoggerMessageAppendedEventArgs(string path, List<string> list)
    {
        Path = path;
        List = list;
    }
}

public delegate void AppendedEventHandler(object sender, LoggerMessageAppendedEventArgs e);

I'm trying to implement own log4net appender, that would group messages by namespace into groups.
Problem is, that i can't get log4net to log LocationInformation, as i would like.

  class Program
{
    protected static IWindsorContainer container;
    static void Main(string[] args)
    {
        container = new WindsorContainer();
        container.Kernel.Resolver.AddSubResolver(new ArrayResolver(container.Kernel));

        // add facilities
        container.AddFacility("logging.facility", new LoggingFacility(LoggerImplementation.Log4net, "log4net.config"));
        container.Register(Component.For<ParentClass>().ImplementedBy<ParentClass>());
        container.Register(Component.For<ChildClass>().ImplementedBy<ChildClass>());                      

        var parentClass = container.Resolve<ParentClass>();
        var childClass = container.Resolve<ChildClass>();
        parentClass.Init();
        childClass.Init();

    }
}

public class ParentClass
{
    private readonly ILogger logger;

    private ILog localLogger;

    public ParentClass(ILogger logger)
    {
        this.logger = logger;
        localLogger = LogManager.GetLogger(GetType());
        logger.Info("ctor ioc logger, type: {0}",GetType().Name);
        localLogger.Info(string.Format("ctor local logger, type: {0}", GetType().Name));
    }

    public void Init()
    {
        logger.Info("init ioc logger, type: {0}", GetType().Name);
        localLogger.Info(string.Format("init local logger, type: {0}", GetType().Name));
    }
}

public class ChildClass : ParentClass
{
    public ChildClass(ILogger logger) : base(logger)
    {

    }
}

output is

2011-03-28 09:58:55 INFO 10 ParentClass - ctor ioc logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ParentClass - ctor local logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ParentClass - ctor ioc logger, type: ChildClass
2011-03-28 09:58:55 INFO 10 ParentClass - ctor local logger, type: ChildClass
2011-03-28 09:58:55 INFO 10 ParentClass - init ioc logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ParentClass - init local logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ParentClass - init ioc logger, type: ChildClass
2011-03-28 09:58:55 INFO 10 ParentClass - init local logger, type: ChildClass

problem is, that log4net class name always outputs as base class name (ParentClass). I've thought initially, that may be castle windsor, that is causing such problem, but as results show, even if i create logger instance manually, it still logs base class name. May be anyone has idea, how to force log4net write actual instance class name?

update

here goes log4net config used:

<appender name="RollingFile" type="log4net.Appender.RollingFileAppender">
  <file value="c:\temp\testlog.log" />
  <appendToFile value="true" />
  <maximumFileSize value="10MB" />
  <maxSizeRollBackups value="2" />

  <layout type="log4net.Layout.PatternLayout">
    <conversionPattern value="%utcdate{yyyy-MM-dd HH:mm:ss} %level %thread %C{1} - %message%newline" />
  </layout>
</appender>

<root>
  <level value="INFO" />
  <appender-ref ref="RollingFile" />      
</root>

output above is what i get, what i expect to get is:

2011-03-28 09:58:55 INFO 10 ParentClass - ctor ioc logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ParentClass - ctor local logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ChildClass - ctor ioc logger, type: ChildClass
2011-03-28 09:58:55 INFO 10 ChildClass - ctor local logger, type: ChildClass
2011-03-28 09:58:55 INFO 10 ParentClass - init ioc logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ParentClass - init local logger, type: ParentClass
2011-03-28 09:58:55 INFO 10 ChildClass - init ioc logger, type: ChildClass
2011-03-28 09:58:55 INFO 10 ChildClass - init local logger, type: ChildClass

update 2

in case anybody needs such thing, here is working appender implementation:

public class GroupStringListAppender : log4net.Appender.AppenderSkeleton
{
    private readonly int listLength = 30;
    private readonly Func<string, string> pathFuction;
    private readonly Dictionary<string, List<string>> messagesDictionary = new Dictionary<string, List<string>>();

    public GroupStringListAppender(int listLength, Func<string, string> pathFuction)
    {
        this.listLength = listLength;
        this.pathFuction = pathFuction;
    }

    public List<string> GetMessages(string path)
    {
        return messagesDictionary[path];
    }        

    protected override void Append(LoggingEvent loggingEvent)
    {
        var msg = loggingEvent.RenderedMessage;
        var path = pathFuction.Invoke(loggingEvent.LoggerName);

        if (!messagesDictionary.ContainsKey(path))
        {
            messagesDictionary.Add(path, new List<string>());
            OnNewPathCreated(path);
        }

        var list = messagesDictionary[path];        

        while (list.Count - listLength > 0)
        {
            list.RemoveAt(0);    
        }

        list.Add(msg);

        OnAppended(path, list);          
    }

    public event AppendedEventHandler Appended;

    public void OnAppended(string path, List<string> list)
    {
        AppendedEventHandler handler = Appended;
        if (handler != null) handler(this, new LoggerMessageAppendedEventArgs(path, list));
    }

    public event NewPathCreatedHandler NewPathCreated;

    public void OnNewPathCreated(string path)
    {
        var handler = NewPathCreated;
        if (handler != null) handler(this, new NewPathCreatedHandlerArgs(path));
    }
}

public delegate void NewPathCreatedHandler(object sender, NewPathCreatedHandlerArgs args);

public class NewPathCreatedHandlerArgs : EventArgs
{
    public string Path { get; set; }

    public NewPathCreatedHandlerArgs(string path)
    {
        Path = path;
    }
}

public class LoggerMessageAppendedEventArgs : EventArgs
{
    public string Path { get; set; }
    public List<string> List { get; set; }

    public LoggerMessageAppendedEventArgs(string path, List<string> list)
    {
        Path = path;
        List = list;
    }
}

public delegate void AppendedEventHandler(object sender, LoggerMessageAppendedEventArgs e);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

十二 2024-11-03 23:00:31

通过使用 %logger 而不是 %C{1},您至少会获得本地记录器所需的结果。

我认为对于国际奥委会你需要做更多的事情。必须对此进行更多调查...

By using %logger instead of %C{1} you will get the desired result at least for the local logger.

I think for IoC you need to do a little more. Have to investigate more on this...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文