简体   繁体   English

在 Log4Net PatternString 中添加自定义字段

[英]Add custom fields in Log4Net PatternString

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我需要从我的应用程序登录到 JSON,所以我组合了一个扩展 LayoutSkeleton 的 Json 布局

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并在我的 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>

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所要求的是,在记录的消息中,我从message object 中删除嵌套,以便日志语句变为

{
  "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.我似乎无法弄清楚的是如何从e.MessageObject中提取值,以便我可以将这些值放入必要的字段中。 From within the debugger I can see that the e.MessageObject is of type object {System.Collections.Generic.Dictionary<string, string>} .在调试器中,我可以看到e.MessageObject的类型为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' .当我尝试使用e.MessageObject["systemId"]像普通字典一样访问它时,我收到以下错误消息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.我不是 .NET 程序员,找不到解决这个愚蠢错误的方法。 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.但这对解决这个问题没有帮助。

object is a kind of generic type that means "I can store nearly anything of nearly any type here". object是一种通用类型,意思是“我可以在这里存储几乎任何类型的任何东西”。 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...你需要让编译器知道你正在处理什么样的 object ...

Something along the lines of:类似的东西:

Dictionary<string,string> messages = e.MessageObject as Dictionary<string,string>;
if(null == messages) {
    // The thing stored here is NOT a Dictionary<string,string>.
    throw new Exception("not the right type");
}
// code to work with the Dictionary...  messages["systemId"]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM