0

是否可以将 npgsql 日志输出重定向到 log4net 记录器?从 npgsql 源代码来看,它看起来像是直接记录到 stdout/stderr 或指定文件(使用 上的静态属性NpgsqlEventLog)。有没有办法将该登录路由到 log4net?

4

3 回答 3

3

这就是我所做的,它似乎工作得相当好。请注意,我将注销命令拆分到单独的附加程序,因为它变得非常冗长......

首先,在对 Npgsql 进行任何其他调用之前添加它:

NpgsqlLogManager.Provider = new Log4NetNpgsqlLoggingProvider("NpgsqlDefaultLogger")
{
    CommandLoggerName = "NpgsqlCommandLogger"
};

现在您需要添加日志记录提供程序类:

using System;
using Npgsql.Logging;

namespace Util.Npgsql
{
    public class Log4NetNpgsqlLoggingProvider : INpgsqlLoggingProvider
    {
        public string DefaultLoggerName { get; }
        public string CommandLoggerName { get; set; }

        public Log4NetNpgsqlLoggingProvider(string defaultLoggerName)
        {
            if (defaultLoggerName == null) throw new ArgumentNullException(nameof(defaultLoggerName));
            DefaultLoggerName = defaultLoggerName;
        }

        public NpgsqlLogger CreateLogger(string name)
        {
            switch (name)
            {
                case "Npgsql.NpgsqlCommand":
                    return new Log4NetNpgsqlLogger(CommandLoggerName ?? DefaultLoggerName);
                default:
                    return new Log4NetNpgsqlLogger(DefaultLoggerName);
            }
        }
    }
}

而且您还需要实际的记录器类:

using System;
using log4net;
using log4net.Core;
using Npgsql.Logging;

namespace Util.Npgsql
{
    public class Log4NetNpgsqlLogger : NpgsqlLogger
    {
        private readonly ILog _log;

        public Log4NetNpgsqlLogger(string name)
        {
            _log = LogManager.GetLogger(name);
        }

        public override bool IsEnabled(NpgsqlLogLevel level)
        {
            return _log.Logger.IsEnabledFor(GetLog4NetLevelFromNpgsqlLogLevel(level));
        }

        public override void Log(NpgsqlLogLevel level, int connectorId, string msg, Exception exception = null)
        {
            _log.Logger.Log(typeof(NpgsqlLogger), GetLog4NetLevelFromNpgsqlLogLevel(level), connectorId + ": " + msg, exception);
        }

        protected Level GetLog4NetLevelFromNpgsqlLogLevel(NpgsqlLogLevel level)
        {
            switch (level)
            {
                case NpgsqlLogLevel.Trace:
                case NpgsqlLogLevel.Debug:
                    return Level.Debug;
                case NpgsqlLogLevel.Info:
                    return Level.Info;
                case NpgsqlLogLevel.Warn:
                    return Level.Warn;
                case NpgsqlLogLevel.Error:
                    return Level.Error;
                case NpgsqlLogLevel.Fatal:
                    return Level.Fatal;
                default:
                    throw new Exception("Unknown Npgsql Log Level: " + level);
            }
        }
    }
}
于 2017-03-30T01:49:52.770 回答
1

首先将 log4net 添加到您的解决方案中,简单的方法是使用 nuget: 所以你这样做: install-Package log4net 然后你必须安装 npgsql: install-Package npgsql

在您的 web.config 文件中添加以下元素:(您必须使用 app.config 而非 Web 解决方案)

在 configSection printf("%d\n", 42); /*

//the most important thing is to ensure that the type on your parameter         //section is correct. otherwise, no error will be returned, and no data will be         inserted.

//now, at your code you can use this function:

        protected void LogInfo(string message, params object[] args)
        {
            log4net.ILog log =     log4net.LogManager.GetLogger("postgreSqlLogAppender");
            log4net.ThreadContext.Properties["UserId"] = args.[0];
            log4net.ThreadContext.Properties["EntityId"] = args.[1];
            log.Info(string.Format("{0}: {1}",     this.GetType().Name.Replace("Controller", ""), string.Format(message, args)));
            log4net.ThreadContext.Properties.Remove("UserId");
            log4net.ThreadContext.Properties.Remove("EntityId");
        }


//to call your function
    void test()
{
   LogInfo("My message",15,326)
}


//in my case 15 is my current user_id and 326 is the my class_object.
     */
于 2015-03-12T19:13:41.883 回答
0

我对npgsql一无所知,但如果你有源并且允许更改它,那么更改它以支持log4net应该更容易。

如果您没有源,那么这将是不容易的,甚至可能是不可能的。由于 log4net 不会拦截来自其他来源的输出,因此我能看到的唯一方法是拥有一个后台线程来监视 npgsql 正在输出到的文件,并且当文件更改时,您需要读取该文件并解析信息,然后使用该信息调用 log4net。

您仍然有 log4net 会认为每个调用都来自您的例程而不是 npgsql 和堆栈跟踪的问题。也只有在每次创建日志条目时 npgsql 都在锁定、打开、写入和关闭文件时才有效。

于 2012-04-11T18:20:43.597 回答