-
Notifications
You must be signed in to change notification settings - Fork 831
Support {Properties} in output templates #944
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@nblumhardt Thank you for the feedback. Without any doubts I missed that requirement 😞 After brief investigation I found two ways to fix it:
Could you tell me what way you prefer or maybe you can advice me another one? Thanks... |
@nblumhardt Anyway, I pushed fix with inspecting MessageTemplate.NamedProperties. |
var delim = ""; | ||
foreach (var kvp in _properties) | ||
{ | ||
if (_template.NamedProperties.Any(x => x.PropertyName == kvp.Key)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since NamedProperties
is an array, this can use indexer-based access and avoid allocating a LINQ enumerator. (Keeping an eye on allocations, as they build up.)
Looking good! Just the minor comment. @serilog/reviewers-core any thoughts on this one? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it
Cool! :-) Me too. I think we should just make the LINQ change then hit the button. |
@nblumhardt I hope I fixed your comment 😉 |
|
||
static bool TemplateContainsPropertyName(MessageTemplate template, string propertyName) | ||
{ | ||
foreach (var namedProperty in template.NamedProperties) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Pliner I actually had the ol' for(var i = ...
in mind here.
Added a clarification. Thanks @Pliner! Just stepping back for a second, there's one scenario where this might not be enough to achieve what we want. I.e. in Serilog.Extensions.Logging.File we use the output template:
To take advantage of this change, we'd want something resembling:
Although we've got Maybe not a show-stopper, but possibly worth a second thought? |
@nblumhardt To be honest, log4net approach is ok for me: if %properties% is used in patternlayout, all properties from all contexts will be captured with any exclusions. |
Thanks for the follow-up Yuri. I guess the difference here is that for log4net, the |
Hey guys, what's the reasoning behind preferring the for loop to the foreach one ? |
@Noctis- microbenchmarks :-) ... less allocation. |
@serilog/reviewers-core any thoughts/opinions on #944 (comment) ? |
I think |
Another quick note that provides more evidence... in Logary we also implemented it by ignoring the fields already in the template. |
Agreed, we should not duplicate. |
@nblumhardt @adamchester @merbla Will make another commit today or tomorow. |
Thank you @Pliner :-) 👍 |
@nblumhardt I'm not sure about my approach, but now I haven't any ideas how to do it differently 😢 |
Great! I think it's about as good as we are likely to get, here, without deeper changes (which we could still consider in the future).
|
@@ -72,7 +72,7 @@ public static class OutputProperties | |||
result[TimestampPropertyName] = new ScalarValue(logEvent.Timestamp); | |||
result[LevelPropertyName] = new LogEventLevelValue(logEvent.Level); | |||
result[NewLinePropertyName] = new LiteralStringValue(Environment.NewLine); | |||
result[PropertiesPropertyName] = new LogEventPropertiesValue(logEvent.MessageTemplate, logEvent.Properties); | |||
result[PropertiesPropertyName] = new LogEventPropertiesValue(logEvent.MessageTemplate, logEvent.Properties, result); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would just add a comment before this line to remind future explorers to make sure this property always comes last so it picks up all the existing properties.
@nblumhardt Sorry, but I have to rewrite implementation, because agait it doesn't do everything right. I should not use output properties, but use output message template instead. |
@adamchester Unfortunatly yes, because previous implementation is simply not working 😞 |
/// <returns>A dictionary with properties representing the log event.</returns> | ||
public static IReadOnlyDictionary<string, LogEventPropertyValue> GetOutputProperties(LogEvent logEvent) | ||
public static IReadOnlyDictionary<string, LogEventPropertyValue> GetOutputProperties(LogEvent logEvent, MessageTemplate outputTemplate) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, this will break the literate console sink binary:
One obvious option would be to:
- Keep this overload
- Add back the one without the additional parameter, but make it forward calls to the full version (we could pass
MessageTemplate.Empty
asoutputTemplate
, so that the arguments could still be null-checked) - Mark the old overload
[Obsolete("Pass the full output template using the other overload.")]
An alternative, which might be worth considering, is to add the new overload as internal
, mark the old one obsolete, and stop offering a public GetOutputProperties()
at some time in the future. With the literate console being the only consumer, it may be defensible to simply duplicate the code there.
I like the latter alternative because it'd allow us to re-think how the MessageTemplateTextFormatter
works in the future - hopefully to improve on the O(N) scans of the message templates - without then needing to break further public API surface.
Any thoughts?
@Pliner good spotting - thanks for the thorough check :-) |
@nblumhardt I made an obvious changes for backward compatibility as you mentioned before. |
🎉 thanks for the great contribution, Yuri! |
Fixes serilog#825 - output template support for `Properties`
Hi guys!
Here is a small addition to the Serilog 😉