Log4Net 似乎连接到数据库但没有插入
Log4Net seems to connect to the database but not Insert
我打开了调试功能,所以我很确定它正在连接到数据库。我这么说是因为如果我拼错了数据库名称,它会向输出写入一个错误。
我不确定我做错了什么。我知道我有一些参数还没有被使用。
我所做的是将 this tutorial 改编成一个项目。如果您需要查看更多信息,请告诉我。
Log4Net.config
<?xml version="1.0" encoding="utf-8" ?>
<log4net debug="true">
<root>
<level value="ALL"/>
<appender-ref ref="AdoNetAppender"/>
<appender-ref ref="DebugAppender"/>
</root>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="1" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="Data Source=server;Initial Catalog=db; User Id=user; Password=pass" />
<commandText value="INSERT INTO LogException ([LogLevel],[LogMessage],[StackTrace],[Object],[CreateDateTime]) VALUES (@log_level, @message, @stacktrace, @exception, @date)" />
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
<parameter>
<parameterName value="@exception" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
<parameter>
<parameterName value="@entryAssembly" />
<dbType value="String" />
<size value="200" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{entryAssembly}" />
</layout>
</parameter>
<parameter>
<parameterName value="@callingAssembly" />
<dbType value="String" />
<size value="200" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{callingAssembly}" />
</layout>
</parameter>
<parameter>
<parameterName value="@method" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{method}" />
</layout>
</parameter>
<parameter>
<parameterName value="@stacktrace" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%stacktrace" />
</layout>
</parameter>
</appender>
</log4net>
Log4netLoggingService.cs
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Logging.Contracts.Log;
using log4net;
using log4net.Appender;
using log4net.Config;
using log4net.Filter;
using log4net.Util;
namespace Logging
{
public class Log4NetLoggingService : ILoggingService
{
private readonly ILog _logger;
static Log4NetLoggingService()
{
var log4NetConfigFilePath = @"C:\Work\folder\Main\Logging\Log4Net.config";
XmlConfigurator.ConfigureAndWatch(new FileInfo(log4NetConfigFilePath));
}
//targets reads from and enum to know where to save.
public Log4NetLoggingService(LogTarget targets = LogTarget.All)
{
_logger = LogManager.GetLogger(new StackFrame(1).GetMethod().DeclaringType);
#if DEBUG
var error = LogManager.GetRepository().ConfigurationMessages.Cast<LogLog>();
#endif
if (targets.HasFlag(LogTarget.All))
return;
SwitchOffLogTargets(targets);
}
protected ILog logger { get { return _logger; } }
public void Fatal(ErrorLogEntry logEntry)
{
logEntry.Level = Level.Fatal.ToString();
if (_logger.IsFatalEnabled)
_logger.Fatal(logEntry);
}
public void Error(ErrorLogEntry logEntry)
{
logEntry.Level = Level.Error.ToString();
if (_logger.IsErrorEnabled)
_logger.Error(logEntry);
}
public void Warn(LogEntry logEntry)
{
logEntry.Level = Level.Warn.ToString();
if (_logger.IsWarnEnabled)
_logger.Warn(logEntry);
}
public void Info(LogEntry logEntry)
{
logEntry.Level = Level.Info.ToString();
if (_logger.IsInfoEnabled)
_logger.Info(logEntry);
}
public void Debug(LogEntry logEntry)
{
logEntry.Level = Level.Debug.ToString();
if (_logger.IsDebugEnabled)
_logger.Debug(logEntry);
}
private void SwitchOffLogTargets(LogTarget targets)
{
var appenders = _logger.Logger.Repository.GetAppenders().ToList();
if (!targets.HasFlag(LogTarget.Database))
{
var db = appenders.FirstOrDefault(piA => piA is AdoNetAppender);
if (db != null)
((AdoNetAppender)db).AddFilter(new DenyAllFilter());
}
if (!targets.HasFlag(LogTarget.TextFile))
{
var file = appenders.FirstOrDefault(piA => piA is RollingFileAppender);
if (file != null)
((RollingFileAppender)file).AddFilter(new DenyAllFilter());
}
if (!targets.HasFlag(LogTarget.Trace))
{
var trace = appenders.FirstOrDefault(piA => piA is AspNetTraceAppender);
if (trace != null)
((AspNetTraceAppender)trace).AddFilter(new DenyAllFilter());
}
}
}
}
更新:
事实证明,我最近的尝试奏效了。我只是拼错了配置文件名。我希望这对将来的人有帮助。我打算写一篇关于此的博客 post。
Log4Net.config
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<root>
<level value="ALL" debug="true"/>
<!--Add the appenders you want to use here-->
<appender-ref ref="AdoNetAppender"/>
<!--to debug log4net. check the output window of Visual Studio-->
<appender-ref ref="DebugAppender"/>
</root>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="1" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="data source=(localdb)\MSSQLLocalDB;initial catalog=log4NetTestDB;integrated security=false;persist security info=True;" />
<commandText value="INSERT INTO LogException ([Message]) VALUES (@message)" />
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
</appender>
</log4net>
ILoggingAdapter
namespace Logging
{
public interface ILoggingAdapter
{
TimeSpan ExecutionTime { get; set; }
int Counter { get; set; }
void Info(string message);
void Warn(string message);
}
}
记录器
namespace Logging
{
public sealed class Logger : ILoggingAdapter
{
private ILog _log = LogManager.GetLogger(typeof(Logger));
public TimeSpan ExecutionTime { get; set; }
public int Counter { get; set; }
public string Info { get; set; }
public string Warn { get; set; }
void ILoggingAdapter.Info(string message)
{
throw new NotImplementedException();
}
void ILoggingAdapter.Warn(string message)
{
_log.Warn(message);
}
}
}
好吧,这么多笔记
- 您是否尝试过以指定用户身份登录数据库并运行您想要的插入查询?
- 您是否尝试过 enabling debug mode 在 log4net 中查看幕后情况?
- 与上述相关,在根目录下使用两个记录器 - 一个用于数据库,另一个用于文件。仅使用数据库日志记录是一个 糟糕 的想法,因为如果数据库失败,您将不会获得有关它失败的日志。至少,您的本地开发环境应该记录到一个文件
- beefycoder has written a ton about understanding log4net 请注意该教程的许多部分
- 我不知道你为什么要做
if (_logger.IsInfoEnabled)
这样的事情 - 这就是 LogInfo
已经 做的事情 .
- 你到底为什么要把
LogEntry
作为参数类型?像这样使用服务 class 的全部意义在于打破对 log4net 的硬依赖。通过使用 class 类型,您刚刚在消费者中创建了对 log4net 的硬依赖。只需传入字符串即可。这样一来,您就不需要整个logEntry.Level = Level.Warn.ToString();
废话
- 文件中的硬编码路径字符串。现在这将不适用于其他开发人员的机器。
- 构造函数中的堆栈检查 - 你现在已经显着减慢了任何使用它的 classes 的构造, 和 它会在构建时给你不同的结果在 RELEASE 模式下,内联打开。而不是使用服务 class,只需创建一个扩展方法或传入您希望记录器作为参数获取的对象,它会做同样的事情。
- 您的代码配置覆盖 xml 配置(我认为...log4net 的优先顺序规则是模糊的 - 这就是我更喜欢 NLog 的重要原因)
SwitchOffLogTargets
为什么!?如果您想要这种行为,只需更改配置文件即可。配置文件可以定义它想要的任何目标并随时更改,但这里您只是假设它恰好包含某些内容。
我打开了调试功能,所以我很确定它正在连接到数据库。我这么说是因为如果我拼错了数据库名称,它会向输出写入一个错误。
我不确定我做错了什么。我知道我有一些参数还没有被使用。
我所做的是将 this tutorial 改编成一个项目。如果您需要查看更多信息,请告诉我。
Log4Net.config
<?xml version="1.0" encoding="utf-8" ?>
<log4net debug="true">
<root>
<level value="ALL"/>
<appender-ref ref="AdoNetAppender"/>
<appender-ref ref="DebugAppender"/>
</root>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="1" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="Data Source=server;Initial Catalog=db; User Id=user; Password=pass" />
<commandText value="INSERT INTO LogException ([LogLevel],[LogMessage],[StackTrace],[Object],[CreateDateTime]) VALUES (@log_level, @message, @stacktrace, @exception, @date)" />
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
<parameter>
<parameterName value="@exception" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
<parameter>
<parameterName value="@entryAssembly" />
<dbType value="String" />
<size value="200" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{entryAssembly}" />
</layout>
</parameter>
<parameter>
<parameterName value="@callingAssembly" />
<dbType value="String" />
<size value="200" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{callingAssembly}" />
</layout>
</parameter>
<parameter>
<parameterName value="@method" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{method}" />
</layout>
</parameter>
<parameter>
<parameterName value="@stacktrace" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%stacktrace" />
</layout>
</parameter>
</appender>
</log4net>
Log4netLoggingService.cs
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Logging.Contracts.Log;
using log4net;
using log4net.Appender;
using log4net.Config;
using log4net.Filter;
using log4net.Util;
namespace Logging
{
public class Log4NetLoggingService : ILoggingService
{
private readonly ILog _logger;
static Log4NetLoggingService()
{
var log4NetConfigFilePath = @"C:\Work\folder\Main\Logging\Log4Net.config";
XmlConfigurator.ConfigureAndWatch(new FileInfo(log4NetConfigFilePath));
}
//targets reads from and enum to know where to save.
public Log4NetLoggingService(LogTarget targets = LogTarget.All)
{
_logger = LogManager.GetLogger(new StackFrame(1).GetMethod().DeclaringType);
#if DEBUG
var error = LogManager.GetRepository().ConfigurationMessages.Cast<LogLog>();
#endif
if (targets.HasFlag(LogTarget.All))
return;
SwitchOffLogTargets(targets);
}
protected ILog logger { get { return _logger; } }
public void Fatal(ErrorLogEntry logEntry)
{
logEntry.Level = Level.Fatal.ToString();
if (_logger.IsFatalEnabled)
_logger.Fatal(logEntry);
}
public void Error(ErrorLogEntry logEntry)
{
logEntry.Level = Level.Error.ToString();
if (_logger.IsErrorEnabled)
_logger.Error(logEntry);
}
public void Warn(LogEntry logEntry)
{
logEntry.Level = Level.Warn.ToString();
if (_logger.IsWarnEnabled)
_logger.Warn(logEntry);
}
public void Info(LogEntry logEntry)
{
logEntry.Level = Level.Info.ToString();
if (_logger.IsInfoEnabled)
_logger.Info(logEntry);
}
public void Debug(LogEntry logEntry)
{
logEntry.Level = Level.Debug.ToString();
if (_logger.IsDebugEnabled)
_logger.Debug(logEntry);
}
private void SwitchOffLogTargets(LogTarget targets)
{
var appenders = _logger.Logger.Repository.GetAppenders().ToList();
if (!targets.HasFlag(LogTarget.Database))
{
var db = appenders.FirstOrDefault(piA => piA is AdoNetAppender);
if (db != null)
((AdoNetAppender)db).AddFilter(new DenyAllFilter());
}
if (!targets.HasFlag(LogTarget.TextFile))
{
var file = appenders.FirstOrDefault(piA => piA is RollingFileAppender);
if (file != null)
((RollingFileAppender)file).AddFilter(new DenyAllFilter());
}
if (!targets.HasFlag(LogTarget.Trace))
{
var trace = appenders.FirstOrDefault(piA => piA is AspNetTraceAppender);
if (trace != null)
((AspNetTraceAppender)trace).AddFilter(new DenyAllFilter());
}
}
}
}
更新:
事实证明,我最近的尝试奏效了。我只是拼错了配置文件名。我希望这对将来的人有帮助。我打算写一篇关于此的博客 post。
Log4Net.config
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<root>
<level value="ALL" debug="true"/>
<!--Add the appenders you want to use here-->
<appender-ref ref="AdoNetAppender"/>
<!--to debug log4net. check the output window of Visual Studio-->
<appender-ref ref="DebugAppender"/>
</root>
<appender name="AdoNetAppender" type="log4net.Appender.AdoNetAppender">
<bufferSize value="1" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<connectionString value="data source=(localdb)\MSSQLLocalDB;initial catalog=log4NetTestDB;integrated security=false;persist security info=True;" />
<commandText value="INSERT INTO LogException ([Message]) VALUES (@message)" />
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="4000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
</appender>
</log4net>
ILoggingAdapter
namespace Logging
{
public interface ILoggingAdapter
{
TimeSpan ExecutionTime { get; set; }
int Counter { get; set; }
void Info(string message);
void Warn(string message);
}
}
记录器
namespace Logging
{
public sealed class Logger : ILoggingAdapter
{
private ILog _log = LogManager.GetLogger(typeof(Logger));
public TimeSpan ExecutionTime { get; set; }
public int Counter { get; set; }
public string Info { get; set; }
public string Warn { get; set; }
void ILoggingAdapter.Info(string message)
{
throw new NotImplementedException();
}
void ILoggingAdapter.Warn(string message)
{
_log.Warn(message);
}
}
}
好吧,这么多笔记
- 您是否尝试过以指定用户身份登录数据库并运行您想要的插入查询?
- 您是否尝试过 enabling debug mode 在 log4net 中查看幕后情况?
- 与上述相关,在根目录下使用两个记录器 - 一个用于数据库,另一个用于文件。仅使用数据库日志记录是一个 糟糕 的想法,因为如果数据库失败,您将不会获得有关它失败的日志。至少,您的本地开发环境应该记录到一个文件
- beefycoder has written a ton about understanding log4net 请注意该教程的许多部分
- 我不知道你为什么要做
if (_logger.IsInfoEnabled)
这样的事情 - 这就是LogInfo
已经 做的事情 . - 你到底为什么要把
LogEntry
作为参数类型?像这样使用服务 class 的全部意义在于打破对 log4net 的硬依赖。通过使用 class 类型,您刚刚在消费者中创建了对 log4net 的硬依赖。只需传入字符串即可。这样一来,您就不需要整个logEntry.Level = Level.Warn.ToString();
废话 - 文件中的硬编码路径字符串。现在这将不适用于其他开发人员的机器。
- 构造函数中的堆栈检查 - 你现在已经显着减慢了任何使用它的 classes 的构造, 和 它会在构建时给你不同的结果在 RELEASE 模式下,内联打开。而不是使用服务 class,只需创建一个扩展方法或传入您希望记录器作为参数获取的对象,它会做同样的事情。
- 您的代码配置覆盖 xml 配置(我认为...log4net 的优先顺序规则是模糊的 - 这就是我更喜欢 NLog 的重要原因)
SwitchOffLogTargets
为什么!?如果您想要这种行为,只需更改配置文件即可。配置文件可以定义它想要的任何目标并随时更改,但这里您只是假设它恰好包含某些内容。