Closed Strandedpirate closed 2 years ago
Hi! Thanks for the note. I don't think there's any bug here - you're using Microsoft.Extensions.Logging's ILogger<T>
, which doesn't really have any native way to mark objects as being serialized except through message templates with @
(even though NLog supports more structured data handling behind the scenes).
I suspect that the @ObjectsScope2
approach could be made to work via NLog's adapter for Microsoft.Extensions.Logging, but I'm not sure whether it fits with the design goals of that library.
This library just accepts whatever structured data NLog passes into it, so I don't think it's the place to make changes in support of this, but I could be wrong (I'm not deeply familiar with NLog - one of the other watchers of this repo may be able to chime in and correct me if so).
Hope this at least provides some more info on why things are as they are :-)
Thanks, I submitted a feature request for ILogger.BeginScope
on NLog's repo to add support for template message syntax.
Specifically for this project though, any idea why using ${scopenested:format=@}
doesn't get inserted into Seq
as raw JSON?
It's getting pumped in as a JSON string, but its not searchable as structured data because its not the raw JSON object.
Current:
{
"Scope": "[ { \"ConnectionId\": \"0HMI3987KKG0L\" }, { \"RequestId\": \"0HMI3987KKG0L:00000009\", \"RequestPath\": \"/Nlog/Test1\" }, { \"ActionId\": \"bd4fb72b-ea24-43d6-8960-5211ec8dbaae\", \"ActionName\": \"Ripple.Rest.Controllers.NlogController.Test1 (Ripple.Rest)\" }, { \"UserName\": \"Unknown User\", \"UserId\": 0 }, { \"OrderId\": 3456, \"ObjectsScope1\": {\"Id\":1, \"Tags\":[{\"Name\":\"global\", \"Description\":\"global tag\"},{\"Name\":\"exactMatch\", \"Description\":\"exactMatch tag\"}]}, \"@ObjectsScope2\": {\"Id\":1, \"Tags\":[{\"Name\":\"global\", \"Description\":\"global tag\"},{\"Name\":\"exactMatch\", \"Description\":\"exactMatch tag\"}]}, \"{@ObjectsScope3}\": {\"Id\":1, \"Tags\":[{\"Name\":\"global\", \"Description\":\"global tag\"},{\"Name\":\"exactMatch\", \"Description\":\"exactMatch tag\"}]} } ]",
}
Versus expected:
{
"Scope": [
{
"ConnectionId":"0HMI3987KKG0L"
},
{
"RequestId":"0HMI3987KKG0L:00000009",
"RequestPath":"/Nlog/Test1"
},
{
"ActionId":"bd4fb72b-ea24-43d6-8960-5211ec8dbaae",
"ActionName":"Ripple.Rest.Controllers.NlogController.Test1 (Ripple.Rest)"
},
{
"UserName":"Unknown User",
"UserId":0
},
{
"OrderId":3456,
"ObjectsScope1":{
"Id":1,
"Tags":[
{
"Name":"global",
"Description":"global tag"
},
{
"Name":"exactMatch",
"Description":"exactMatch tag"
}
]
},
"@ObjectsScope2":{
"Id":1,
"Tags":[
{
"Name":"global",
"Description":"global tag"
},
{
"Name":"exactMatch",
"Description":"exactMatch tag"
}
]
},
"{@ObjectsScope3}":{
"Id":1,
"Tags":[
{
"Name":"global",
"Description":"global tag"
},
{
"Name":"exactMatch",
"Description":"exactMatch tag"
}
]
}
}
]
}
Thanks for the update. The target/Seq don't try to automatically determine whether a value in a string is valid JSON; the value needs to reach the target as structured data before it will be inlined into the payload as an object with properties and values. If the value is pre-formatted as a string, even a JSON string, it will remain a string through the whole pipeline.
BTW using NLog directly is likely to have better support for structured data in its API than MEL does; it might be worth asking how to achieve what you're after using an NLog ILogger
directly, if the MEL wrapper doesn't have the features you need. HTH!
Thanks, I actually wound up ditching NLog. The bare bones MS ILogger interface by itself, does precisely what I'm after, and allows message template syntax in the ILogger.BeginScope
overloads.
NLog.Targets.Seq uses NLog JsonLayout, so you can do this:
"type": "Seq",
"serverUrl": "http://localhost:4005",
"apiKey": "",
"properties": [
{
"name": "Level",
"value": "${level}"
},
{
"name": "Scope",
"value": "${scopenested:format=@}",
"As": "number"
},
{
"name": "CacheValueTest",
"value": "${scopeproperty:CacheValue:format=@}",
"As": "number"
}
]
Little weird with this magic-value for "As" in SeqPropertyItem. It would probably be more logical if the property was called "AsString" (default=true).
I'm trying to use
ILogger.BeginScope
to record structured object data, and have it recorded inSeq
in JSON format so it can be queried, but it's consistently showing up as just strings, which is doesn't allow me to query it. I posted some of the issue here stackoverflow, and also tried one of the viable suggestions, but it doesn't work either.I'm not sure if this is an issue in NLog or NLog.Targets.Seq.
I made an example web api controller in my .net 6 c# app for testing this, and the output in
Seq
is below after running it.In the following test, only the first row (
ObjectsOp2
) generates the desired JSON format inSeq
that is actually searchable as structured data.I tried one of the viable stackoverflow suggestions of using a scope level layout
${scopenested:format=@}
, but that produces JSON in string format rather than raw JSON inSeq
, so it's not searchable or a workable solution. It gets output in each log as theScope
property.Is there a bug in NLog.Targets.Seq specifically for the layout
${scopenested:format=@}
? Seems like that should work.NlogController
appsettings.json
row 1
row 2
row 3