在log4net模式斯特林中添加自定义字段
我正在努力将记录模式纳入公司设定的标准,并可以使用一些帮助。我需要将我的应用程序登录到JSON中,因此我将JSON布局放在一起,该布局将LayoutsKeleton扩展
public class JsonLayout : LayoutSkeleton
{
public override void ActivateOptions()
{
}
public override void Format(TextWriter writer, LoggingEvent e)
{
var dic = new Dictionary<string, object>
{
["level"] = e.Level.DisplayName,
["message"] = e.MessageObject,
["timestampUtc"] = e.TimeStamp.ToUniversalTime().ToString("O"),
["userName"] = e.UserName
};
writer.WriteLine(JsonConvert.SerializeObject(dic));
}
}
并在我的app.config中引用如下
<appender name="file" type="log4net.Appender.RollingFileAppender,log4net">
<rollingStyle value="Date" />
<datePattern value="yyyy-MM-dd" />
<preserveLogFileNameExtension value="true" />
<staticLogFileName value="false" />
<file type="log4net.Util.PatternString" value="c:\\Logs\\.log" />
<layout type="MyPackage.JsonLayout">
</layout>
</appender>
,然后当我们登录时,这很简单:
Dictionary<string, string> logObject = new Dictionary<string, string>
{
{ "systemId", systemId },
{ "workflowId", workflowId },
{ "transitionName", transitionName },
{ "instrumentId", instrumentId },
{ "instrumentName", instrumentName },
{ "commandId", commandId.ToString() },
{ "message", statusMessage }
};
Logger.Info(logObject);
这起作用。但是,最终被登录的是,
{
"level": "INFO",
"message": {
"systemId": "LM9125",
"workflowId": "WF7656789876",
"transitionName": "My transition",
"instrumentId": "LM123",
"instrumentName": "Centrifuge 1",
"commandId": "d21fb5fa-5b39-4c43-94cc-72dc6a7a174d",
"message": "Centrifuge 1 started"
},
"timestampUtc": "2022-05-06T20:23:06.5136166Z",
"userName": "labuser"
}
请求的是,在登录消息中,我从Message> Message>“
对象”中删除嵌套,以便Log语句变为
{
"level": "INFO",
"systemId": "LM9125",
"workflowId": "WF7656789876",
"transitionName": "My transition",
"instrumentId": "LM123",
"instrumentName": "Centrifuge 1",
"commandId": "d21fb5fa-5b39-4c43-94cc-72dc6a7a174d",
"message": "Centrifuge 1 started",
"timestampUtc": "2022-05-06T20:23:06.5136166Z",
"userName": "labuser"
}
我已将格式方法更新到是
...
var dic = new Dictionary<string, object>
{
["level"] = e.Level.DisplayName,
["systemId"] = "",
["workflowId"] = "",
["transitionName"] = "",
["instrumentId"] = "",
["instrumentName"] = "",
["message"] = e.MessageObject,
["timestampUtc"] = e.TimeStamp.ToUniversalTime().ToString("O"),
["userName"] = e.UserName
};
writer.WriteLine(JsonConvert.SerializeObject(dic));
...
什么我似乎无法弄清楚如何将这些值从e.messageObject
中提取出来,以便我可以将值放入必要的字段中。在调试器中,我可以看到e.messageObject
是类型Object {System.Collections.generic.dictionary&lt; string,String&gt;}
。
当我尝试通过使用e.MessageObject [“ SystemId”]
获得以下错误消息错误CS0021:无法将索引[]应用于类型的表达式时'对象'
。我不是.NET程序员,也找不到解决此愚蠢错误的解决方案。请帮忙!
我已经在堆栈溢出上进行了搜索,我发现的最接近的答案是这个。但这对于解决这个问题并不有帮助。
I'm working on getting my logging pattern into a standard set by my company and could use some help. I need to log from my application into JSON, so I put together a Json layout that extends the LayoutSkeleton
public class JsonLayout : LayoutSkeleton
{
public override void ActivateOptions()
{
}
public override void Format(TextWriter writer, LoggingEvent e)
{
var dic = new Dictionary<string, object>
{
["level"] = e.Level.DisplayName,
["message"] = e.MessageObject,
["timestampUtc"] = e.TimeStamp.ToUniversalTime().ToString("O"),
["userName"] = e.UserName
};
writer.WriteLine(JsonConvert.SerializeObject(dic));
}
}
and reference it in my app.config as follows
<appender name="file" type="log4net.Appender.RollingFileAppender,log4net">
<rollingStyle value="Date" />
<datePattern value="yyyy-MM-dd" />
<preserveLogFileNameExtension value="true" />
<staticLogFileName value="false" />
<file type="log4net.Util.PatternString" value="c:\\Logs\\.log" />
<layout type="MyPackage.JsonLayout">
</layout>
</appender>
And then when we log, it's simple:
Dictionary<string, string> logObject = new Dictionary<string, string>
{
{ "systemId", systemId },
{ "workflowId", workflowId },
{ "transitionName", transitionName },
{ "instrumentId", instrumentId },
{ "instrumentName", instrumentName },
{ "commandId", commandId.ToString() },
{ "message", statusMessage }
};
Logger.Info(logObject);
This works. However, what ends up getting logged is
{
"level": "INFO",
"message": {
"systemId": "LM9125",
"workflowId": "WF7656789876",
"transitionName": "My transition",
"instrumentId": "LM123",
"instrumentName": "Centrifuge 1",
"commandId": "d21fb5fa-5b39-4c43-94cc-72dc6a7a174d",
"message": "Centrifuge 1 started"
},
"timestampUtc": "2022-05-06T20:23:06.5136166Z",
"userName": "labuser"
}
What has been requested is that in the logged message I remove the nesting from within the message
object so that the log statement becomes
{
"level": "INFO",
"systemId": "LM9125",
"workflowId": "WF7656789876",
"transitionName": "My transition",
"instrumentId": "LM123",
"instrumentName": "Centrifuge 1",
"commandId": "d21fb5fa-5b39-4c43-94cc-72dc6a7a174d",
"message": "Centrifuge 1 started",
"timestampUtc": "2022-05-06T20:23:06.5136166Z",
"userName": "labuser"
}
I've updated the Format method to be
...
var dic = new Dictionary<string, object>
{
["level"] = e.Level.DisplayName,
["systemId"] = "",
["workflowId"] = "",
["transitionName"] = "",
["instrumentId"] = "",
["instrumentName"] = "",
["message"] = e.MessageObject,
["timestampUtc"] = e.TimeStamp.ToUniversalTime().ToString("O"),
["userName"] = e.UserName
};
writer.WriteLine(JsonConvert.SerializeObject(dic));
...
What I can't seem to figure out is how to pull the values out of the e.MessageObject
so I can put the values into the necessary fields. From within the debugger I can see that the e.MessageObject
is of type object {System.Collections.Generic.Dictionary<string, string>}
.
When I try to access it like a normal dictionary by using e.MessageObject["systemId"]
I get the following error message error CS0021: Cannot apply indexing with [] to an expression of type 'object'
. I'm not a .NET programmer and cannot find a solution to this silly error. Please help!
I've searched on stack overflow and the closest answer I've found is this. But it wasn't helpful in getting around this problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
对象
是一种通用类型,意味着“我可以在这里存储几乎任何类型的任何类型”。因此,编译器不知道会有哪种类型,因此拒绝将索引语义应用于其。您需要让编译器知道您要处理的是什么样的对象...
类似于:
object
is a kind of generic type that means "I can store nearly anything of nearly any type here". So the compiler doesn't know what type will be there, so it's refusing to apply the indexing semantics to it.You need to let the compiler know what kind of object you are dealing with...
Something along the lines of: