Log4Net似乎连接到数据库,但不是Insert



我已经打开了调试,所以我很确定它正在连接到数据库。我这么说是因为如果我拼错了数据库名称,它会在输出中写入错误。

我不确定我做错了什么。我知道我有参数尚未使用。

我所做的是将本教程改编成一个项目。如果您需要查看更多内容,请告诉我。

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:WorkfolderMainLoggingLog4Net.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());
}
}
}
}

更新:

事实证明,我最近的尝试有效。我只是拼错了配置文件名。我希望这对将来的某人有所帮助。我打算写一篇关于这个的博客文章。

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>

IoggingAdapter

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);
}
}
}

好吧,所以几个注意事项

  • 您是否尝试过以指定用户身份登录到数据库并运行所需的插入查询?
  • 您是否尝试过在log4net中启用调试模式以查看引擎盖下发生了什么?
  • 与上述相关,在根目录中使用两个记录器 - 一个用于数据库,另一个用于文件。仅使用数据库日志记录是一个糟糕的主意,因为如果数据库失败,您将不会获得有关它失败的日志。至少,您的本地开发环境应该记录到一个文件中
  • Beefycoder写了很多关于理解log4net的文章,请注意该教程的许多部分
  • 我不知道你为什么要做像if (_logger.IsInfoEnabled)这样的事情——这就是LogInfo已经做的事情
  • 您到底为什么要将LogEntry作为参数类型?使用这样的服务类的全部意义在于打破对 log4net 的硬依赖。通过使用该类类型,您刚刚在消费者中创建了对 log4net 的硬依赖。只需传入字符串即可。同样这样你就不需要那么logEntry.Level = Level.Warn.ToString();废话了
  • 文件中的硬编码路径字符串。现在,这在其他开发人员的计算机上不起作用。
  • 构造函数中的堆栈检查 - 您现在已经大大减慢了使用它的任何类的构造速度,并且在打开内联的 RELEASE 模式下构建时,它会给你不同的结果。与其使用服务类,不如创建一个扩展方法或传入您希望记录器作为参数来源的对象,该参数执行相同的操作。
  • 您的代码配置会覆盖 xml 配置(我认为...log4net的优先级规则是模糊的 - 这是我更喜欢NLog的重要原因(
  • SwitchOffLogTargets为什么!?如果需要该行为,只需更改配置文件即可。配置文件可以定义它想要的任何目标,并随时更改,但在这里你只是假设它恰好有某些东西。

最新更新