我的网站提供的网络服务很少。这是我想达到的目标:
我的初衷是使用log4net。但是从这些演练(http://sadi02.wordpress.com/2008/09/15/how-to-store-log-in-database-using-log4net/, http://logging.apache.org/log4net/release/config-examples.html)我不知道查看将自定义数据添加到日志表中的简单方法。
将log4net用于此类目的是否可行?如何更改日志表架构以存储自定义数据?我应该修改log4net库的源代码吗?编写自定义功能来存储这类数据可能会更好吗?
感谢。
答案 0 :(得分:14)
根据这个discussion,这个过程非常简单。
第一步是将appender声明中的命令文本更新到配置文件中:
<commandText value="INSERT INTO Log4Net ([Date],[Thread],[Level],[Logger],[Message],[Exception],[MyColumn]) VALUES (@log_date, @thread, @log_level, @logger, @message, @exception,@MyColumn)"/>
下一步是为自定义列添加新的参数定义:
<parameter>
<parameterName value="@MyColumn "/>
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{MyColumn}" />
</layout>
</parameter>
最后,您可以通过log4net的GlobalContext属性访问该值:
log4net.GlobalContext.Properties["MyColumn"] = "MyValue";
log.Debug("My message");
您可以根据需要为多个字段执行此操作。
答案 1 :(得分:2)
建议的答案都不适合我。问题是我需要有几个自定义字段。对我来说,创建不同的记录器实例或每次通过'属性'设置列值似乎太复杂了。
我将(实际上已经实现)将数据放入数据库的自定义记录器。
答案 2 :(得分:1)
查看log4net文档,您能想出如何将自定义数据记录到文件中吗?如果是这样,您还应该能够将相同的数据记录到数据库中。只需在表格中添加更多列,在AdoNetAppender的<command text>
节点中添加更多列,以及更多<parameter>
个节点。
我认为您需要做一些工作来记录传入和传出的参数。你需要他们登录在单独的列中(可能不容易干净)?如果它们与消息一起记录是否可以?
例如,如果您要将以下方法放入登录:
public void DoSomething(int x, int y)
{
log.Info("Inside DoSomething");
}
您希望输出看起来像什么?您是否希望“标准”log4net信息显示在单独的列中(时间戳,记录器名称,级别,消息)?参数怎么样? x和y应该出现在不同的列中(除非每个方法都有相同数量的参数,否则可能不是很容易)或者如果参数记录如下就可以了:
public void DoSomething(int x, int y)
{
ILog log = LogManager.GetLogger("abc");
log.InfoFormat("Parameters: x = {0}, y = {1}", x, y);
log.Info("Inside DoSomething");
}
日志语句将生成如下所示的消息:
11/29/2010 16:36:00 | abc | INFO | Parameters: x = 10, y = 20
11/29/2010 16:36:00 | abc | INFO | Inside DoSomething
我用过|字符,用于显示带有时间戳,loggername,日志级别和消息的模式布局的字段。
查看像PostSharp这样的AOP解决方案可能对您有所帮助,因为您可以相对轻松地添加进入/退出日志记录,而无需使用日志记录语句“污染”您的应用程序源代码。在日志“方面”内部,您可以访问该方法的参数。
我可能会遗漏一些东西,但我怀疑如果你想将你的方法参数作为数据库中的单个列维护,那么你会发现很难做到。如果您对将每个方法的所有参数(手动)组合为单个列(本质上是格式化的字符串)感到满意,那么这将更容易。您必须支付的一个价格是您必须明确记录所有参数(除非您使用AOP路线)。
如果您正在考虑使用log4net,您还应该考虑使用NLog。它不一定会帮助你解决我上面描述的问题,但我认为它是log4net的一个有价值的竞争对手。
[编辑]
要获取log4net记录的“组件名称”,您应该为组件命名记录器。当您调用LogManager.GetLogger(名称)时,您可以传递任何名称(或类型)。一个常见的模式是在每个类中都有这样的代码:
public class MyClass
{
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
public void DoSomething(int x)
{
logger.InfoFormat("Inside DoSomething. x = {0}", x);
}
}
这将获得一个以完全限定的类名(命名空间+类名)命名的记录器。如果你在每个类中都这样做,那么你可以控制每个类的日志记录(级别,它进入哪个appender等)。因此,您可以轻松地将Class1的日志记录转换为Info并记录Class2 Off等。这使您可以最大程度地控制日志记录。
现在,在您的配置文件中,您没有义务明确列出每个记录器(即每个完全限定的类名)。您可以只配置根记录器,然后这些设置将应用于每个记录器。您可以通过命名空间控制日志记录。例如,如果您使用CompanyX并且您具有明确的命名空间规则,则您的命名空间可能如下所示:
CompanyX
CompanyX.DataAccess
CompanyX.DataAccess.Read
CompanyX.DataAccess.Write
CompanyX.GUI
CompanyX.Forms
CompanyX.Controls
在每个命名空间中,您可能有各种类(如几个不同的数据读取器,辅助类,数据编写器等)。对于像这样组织的类,并且您的类如上所述获取记录器,您可以轻松地为CompanyX中的所有类或CompanyX.DataAccess或CompanyX.DataAccess.Read等中的所有记录器配置日志记录。您甚至可以关闭所有日志记录,但是为那个给你带来麻烦的麻烦课程打开它。
您还可以通过任意名称获取记录器(例如,如果您不想使用,则不必使用类名)。您可以在应用程序中定义功能区域,并根据以下内容获取记录器:
ILog logger = LogManager.GetLogger("DataAccess");
ILog logger = LogManager.GetLogger("Performance");
ILog logger = LogManager.GetLogger("UI");
等等。我没有看到这比使用完全限定的类名有很多好处。如果您的命名空间组织良好,那么您配置日志记录的能力将具有最大的灵活性,而您只需付出最小的努力。
NLog上的另一个词...... NLog与log4net非常相似。它确实具有能够自动返回当前类的记录器的有用功能:
Logger logger = NLog.LogManager.GetCurrentClassLogger();
这至少可以节省一些打字。 NLog刚刚发布了一个新版本(目前处于测试阶段)。
不知道是否有任何帮助,但我希望它能做到!
祝你好运!