0

I am trying to get Common.Logging to call my custom logger, but WriteInternal is never called. Did I miss a configuration somewhere? In my ASP.NET Owin project, Startup.cs has

        LogManager.Adapter = new HubLoggerAdapter(resolver.Kernel.Get<ILogger>());

where ILogger is my custom logger. HubLoggerAdapter looks like

public class HubLoggerAdapter : ILoggerFactoryAdapter
{
    private ILogger _logger;

    public HubLoggerAdapter(ILogger logger)
    {
        _logger = logger;
    }

    public ILog GetLogger(Type type)
    {
        if (type == null)
        {
            throw new ArgumentNullException("type");
        }

        try
        {
            return new HubLogger(_logger);
        }
        catch (Exception ex)
        {
            var x = ex.Message;
        }
        return null;
    }

    public ILog GetLogger(string name)
    {
        if (name == null)
        {
            throw new ArgumentNullException();
        }

        try
        {
            return new HubLogger(_logger);
        }
        catch (Exception ex)
        {
            var x = ex.Message;
        }
        return null;
    }
}

and the logger looks like

public class HubLogger : AbstractLogger
{
    public override bool IsTraceEnabled { get { return _logLevel.HasFlag(LogLevel.Trace); } }
    public override bool IsDebugEnabled { get { return _logLevel.HasFlag(LogLevel.Debug); } }
    public override bool IsErrorEnabled { get { return _logLevel.HasFlag(LogLevel.Error); } }
    public override bool IsFatalEnabled { get { return _logLevel.HasFlag(LogLevel.Fatal); } }
    public override bool IsInfoEnabled { get { return _logLevel.HasFlag(LogLevel.Info); } }
    public override bool IsWarnEnabled { get { return _logLevel.HasFlag(LogLevel.Warn); } }

    private LogLevel _logLevel;
    private ILogger _logger;

    public HubLogger(ILogger logger)
        : this(logger, LogLevel.All)
    {

    }

    public HubLogger(ILogger logger, LogLevel level)
        : base()
    {            
        _logLevel = level;
        _logger = logger;

        _logger.Log("initiating HubLogger");
    }

    protected override void WriteInternal(LogLevel level, object message, Exception exception)
    {
        switch (level)
        {
            case LogLevel.All:
            case LogLevel.Trace:
            case LogLevel.Debug:
            case LogLevel.Info:
            case LogLevel.Warn:
            case LogLevel.Error:
                _logger.Log(message.ToString());
                if (exception != null)
                {
                    _logger.Log(exception);
                }
                break;
            case LogLevel.Off:
                break;

            default:
                throw new ArgumentOutOfRangeException("level", level, "invalid logging level");
        }
    }
}

If I call var logger = LogManager.GetLogger(); logger.Warn("I'm alive.");

I see "initiating HubLogger" but then WriteInternal is never called for my message. It is really odd. Any insight much appreciated.

Edit 1. Tried to add constructor with NameValueCollection per suggestion, but it did not work. Specifically added

    private ILogger _logger;
    public IKernel Kernel { get; set; }

    public HubLoggerAdapter(NameValueCollection props)
    {

// _logger = props["logger"]; }

    public HubLoggerAdapter(ILogger logger)
    {
        _logger = logger;
    }

and used

        var props = new NameValueCollection();
        var adapter = new HubLoggerAdapter(props);
        adapter.Kernel = resolver.Kernel;
        LogManager.Adapter = adapter;

not sure why the constructor would make any difference.

tofutim
  • 22,664
  • 20
  • 87
  • 148
  • 1
    http://netcommon.sourceforge.net/docs/1.2.0/reference/html/logging.html: 1.5.1: "Important: Any implementation must provide a public constructor accepting a NameValueCollection parameter" – Caramiriel Oct 27 '16 at 19:51
  • I wonder how I can pass my object in there then. – tofutim Oct 27 '16 at 21:38
  • and that is really odd too, don't we create it ourselves? I tried your suggestion, but it did not help – tofutim Oct 27 '16 at 21:53

1 Answers1

0

I finally got this to work by deriving from AbstractSimpleLogger and AbstractSimpleLoggerFactoryAdapter.

public class HubLogger : AbstractSimpleLogger
{
    private ILogger _logger;

    public HubLogger(ILogger logger, string logName, LogLevel logLevel, bool showLevel, bool showDateTime, bool showLogName, string dateTimeFormat)
        : base(logName, logLevel, showLevel, showDateTime, showLogName, dateTimeFormat)
    {
        _logger = logger;
    }

    protected override void WriteInternal(LogLevel level, object message, Exception e)
    {
        switch (level)
        {
            case LogLevel.All:
            case LogLevel.Trace:
            case LogLevel.Debug:
            case LogLevel.Info:
            case LogLevel.Warn:
            case LogLevel.Error:
                // Use a StringBuilder for better performance
                StringBuilder sb = new StringBuilder();
                FormatOutput(sb, level, message, e);

                if (e != null)
                {
                    _logger.Log(e);
                }
                _logger.Log(sb.ToString());
                break;
            case LogLevel.Off:
                break;

            default:
                throw new ArgumentOutOfRangeException("level", level, "invalid logging level");
        }
    }

and

    private ILogger _logger;

    public HubLoggerAdapter(ILogger logger)
        : base(null)
    {
        _logger = logger;
    }

    protected override ILog CreateLogger(string name, LogLevel level, bool showLevel, bool showDateTime, bool showLogName, string dateTimeFormat)
    {
        ILog log = new HubLogger(_logger, name, level, showLevel, showDateTime, showLogName, dateTimeFormat);
        return log;
    }
}
tofutim
  • 22,664
  • 20
  • 87
  • 148