C# 如何将 NLog 中的自定义字段记录到数据库?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12424301/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I log a custom field in NLog to database?
提问by Kjensen
I currently use NLog on a lot of projects. On some, I log to a database.
我目前在很多项目中使用 NLog。在某些情况下,我登录到数据库。
Here is what I would like to do:
这是我想做的事情:
CREATE TABLE [dbo].[NLogEntries](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[Origin] [nvarchar](100) NOT NULL,
[LogLevel] [nvarchar](20) NOT NULL,
[Message] [nvarchar](3600) NOT NULL,
[CreatedOn] [datetime] NOT NULL,
[OrderId] [int] NULL --Custom field!
)
And NLog.config with this target:
和 NLog.config 与此目标:
<target type="Database" name="database" connectionstring="Server=localhost;Database=NLog;Trusted_Connection=True;">
<commandText>
INSERT INTO NLogEntries ([Origin], [Message], [LogLevel],[CreatedOn],[OrderId]) VALUES (@Origin,@Message,@LogLevel,@Date, @OrderId);
</commandText>
<parameter name="@Date" layout="${date}"/>
<parameter name="@Origin" layout="${callsite}"/>
<parameter name="@LogLevel" layout="${level}"/>
<parameter name="@message" layout="${message}"/>
<parameter name="@OrderId" layout="${orderId}"/> <!-- custom field! -->
</target>
And then log something like this:
然后记录如下内容:
var logger = LogManager.GetCurrentClassLogger();
var orderId = 123;
logger.Debug("What is going on here", orderId);
Is there a good way to do this and keep using NLog? Or do I have to roll my own logger and skip NLog when these are the requirements?
有没有好的方法可以做到这一点并继续使用 NLog?或者我是否必须滚动自己的记录器并在满足这些要求时跳过 NLog?
采纳答案by Michael Freidgeim
Rather than using GDC, which is for global static data and fails on concurrent logging, it is better to use?EventProperties-Layout-Renderer?that allows to pass custom ?properties?specific for the event
与其使用GDC,后者用于全局静态数据并且并发日志记录失败,不如使用?EventProperties-Layout-Renderer?允许传递自定义的?属性?特定于事件
LogEventInfo theEvent = new LogEventInfo(logLevel, "", message);
theEvent.Properties["OrderId"] =orderId;`
log.Log(theEvent);
... and in your NLog.config file:
${event-context:item=OrderId} -- obsolete
${event-properties:item=OrderId} -- renders OrderId
回答by wageoghe
Here is one approach using the GlobalContext.
这是使用 GlobalContext 的一种方法。
Configuration:
配置:
<target type="Database" name="database" connectionstring="Server=localhost;Database=NLog;Trusted_Connection=True;">
<commandText>
INSERT INTO NLogEntries ([Origin], [Message], [LogLevel],[CreatedOn],[OrderId]) VALUES (@Origin,@Message,@LogLevel,@Date, @OrderId);
</commandText>
<parameter name="@Date" layout="${date}"/>
<parameter name="@Origin" layout="${callsite}"/>
<parameter name="@LogLevel" layout="${level}"/>
<parameter name="@message" layout="${message}"/>
<parameter name="@OrderId" layout="${gdc:OrderId}"/> <!-- custom field! -->
</target>
Call site:
呼叫站点:
var logger = LogManager.GetCurrentClassLogger();
GlobalDiagnosticsContext.Set("OrderId",123);
logger.Debug("What is going on here"); //If you use the logging configuration above, 123 will be logged to the OrderId column in your database
With a little more effort, you could wrap the NLog logger using one of the techniques illustrated here.
只需稍加努力,您就可以使用此处说明的技术之一包装 NLog 记录器。
Or, you could create your own "context" object and write a custom LayoutRenderer to pull the values from it and write them to the log. Custom LayourRenderers are easy to write. You can see one example in my first answer to this question. There, I show how to write your own LayoutRenderer that appends the current value of System.Diagnostics.Trace.CorrelationManager.ActivityId to the log message.
或者,您可以创建自己的“上下文”对象并编写自定义 LayoutRenderer 以从中提取值并将它们写入日志。自定义LayourRenderer 很容易编写。你可以在我对这个问题的第一个回答中看到一个例子。在那里,我展示了如何编写您自己的 LayoutRenderer,将 System.Diagnostics.Trace.CorrelationManager.ActivityId 的当前值附加到日志消息。
回答by Eldar
You can use the MDC code:
您可以使用 MDC 代码:
var logger = LogManager.GetCurrentClassLogger();
MDC.Set("OrderId", 123);
MDC.Set("user", HttpContext.Current.User.Identity.Name);
// ... and so on
also check this http://weblogs.asp.net/drnetjes/archive/2005/02/16/374780.aspx
也检查这个http://weblogs.asp.net/drnetjes/archive/2005/02/16/374780.aspx
回答by Balash
If that's all one needs, as of NLog version 4.3.3 there's an easier way to declare and access custom variables. Beware:none of these solutions are thread-safe.
如果这就是全部需求,那么从 NLog 4.3.3 版开始,有一种更简单的方法来声明和访问自定义变量。 注意:这些解决方案都不是线程安全的。
Add the following to the NLog.config
将以下内容添加到 NLog.config
<nlog ...
<!-- optional, add some variables -->
...
<variable name="myvarone" value="myvalue"/>
<variable name="myvartwo" value=2/>
...
</nlog>
Variables can be changed/accessed in the code by:
可以通过以下方式在代码中更改/访问变量:
LogManager.Configuration.Variables["myvarone"] = "New Value"
LogManager.Configuration.Variables["myvartwo"] = 2
The values can be referenced in NLog.config:
这些值可以在 NLog.config 中引用:
"${var:myvarone}" -- renders "New Value"
"${var:myvartwo}" -- renders 2
As I mentioned above varand LogEventInfoobjects are global. So if multiple instances are defined, changing a value would change the value for all instances. I'm very interested if anyone knows a way to declare per instance custom variables for NLog.
正如我上面提到的var和LogEventInfo对象是全局的。因此,如果定义了多个实例,更改一个值将更改所有实例的值。如果有人知道为 NLog 声明每个实例的自定义变量的方法,我很感兴趣。
回答by Julian
With NLog 4.6.3 this is now easier and thread safe!
使用 NLog 4.6.3,这现在更容易且线程安全!
Call
称呼
int orderId = 123;
logger.WithProperty("MyOrderId", orderId).Info("This is my message!");
Config:
配置:
<target type="Database" name="database" connectionstring="Server=localhost;Database=NLog;Trusted_Connection=True;">
<commandText>
INSERT INTO NLogEntries ([Origin], [Message], [LogLevel],[CreatedOn],[OrderId]) VALUES (@Origin,@Message,@LogLevel,@Date, @OrderId);
</commandText>
<parameter name="@Date" layout="${date}" dbType="DbType.Date"/>
<parameter name="@Origin" layout="${callsite}"/>
<parameter name="@LogLevel" layout="${level}"/>
<parameter name="@message" layout="${message}"/>
<parameter name="@OrderId" layout="${event-properties:MyOrderId}" dbType="DbType.Int32"/> <!-- custom field! Note also the DB Type -->
</target>
Note, NLog 4.6 has also support for DbType - See https://nlog-project.org/2019/03/20/nlog-4-6-is-live.html
请注意,NLog 4.6 还支持 DbType - 请参阅https://nlog-project.org/2019/03/20/nlog-4-6-is-live.html

