是否可以将npgsql日志输出重定向到log4net记录器?从npgsql源代码看,它看起来直接记录到stdout / stderr或指定文件(使用NpgsqlEventLog
上的静态属性)。有没有办法将登录路由到log4net?
答案 0 :(得分:2)
我就是这样做的,而且似乎工作得相当好。请注意,我正在将命令注销到单独的appender,因为它变得非常冗长......
首先,在对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);
}
}
}
}
答案 1 :(得分:1)
我对npgsql一无所知,但是如果您有源并且允许更改它,那么应该更容易更改它以支持log4net。
如果您没有来源,那么这并不容易,甚至可能无法实现。由于log4net不拦截来自其他源的输出,我能看到的唯一方法就是有一个后台线程来监视npgsql输出的文件,当文件发生变化时,你需要读取该文件并解析信息,然后使用该信息调用log4net。
你仍然有一个问题,即log4net会认为每个调用都来自你的例程而不是npgsql和堆栈跟踪搞砸了。也只有在每次创建日志条目时npgsql锁定,打开,写入和关闭文件时才会起作用。
答案 2 :(得分: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.
*/