Skip to content

Fixes #50 - include named scopes #55

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

Merged
merged 4 commits into from
Nov 15, 2016
Merged

Fixes #50 - include named scopes #55

merged 4 commits into from
Nov 15, 2016

Conversation

nblumhardt
Copy link
Member

When includeNamedScopes is specified as true in the AddSerilog() call, string-valued scope data will be included in a new property called Scope on the resulting log events:

using (logger.BeginScope("Outer"))
{
    logger.LogInformation("Outer");

    using (logger.BeginScope("Inner"))
    {
        logger.LogInformation("Inner");
    }

    logger.LogInformation("Outer, again");
}

logger.LogInformation("Done");

image

No breaking changes, though a few constructors were added to SerilogLoggerProvider to facilitate this.

Alternatives

The opt-in nature of the change is following the console logger provider, which requires includeScopes to be passed for scope information to be recorded.

It could make sense to enable this by default, since developers are essentially opting in with BeginScope(), and object-valued (i.e. key-value-pair) scope state is already included.

Thoughts?

@nblumhardt
Copy link
Member Author

Switched to an opt-out. The parameter is now ignoreNamedScopes = false.

@nblumhardt
Copy link
Member Author

nblumhardt commented Nov 14, 2016

One other consideration; properties added with BeginScope(new Dictionary<string,object>{ ["A"] = 1 }) will be pushed onto the LogContext; named scope properties as implemented in this PR won't.

The original reason for pushing named properties onto LogContext was to carry though the RequestId and other properties added by ASP.NET middleware during the request handling lifecycle. I think it would be consistent to handle named scopes in the same way, but not necessarily advantageous to do so.

@nblumhardt
Copy link
Member Author

@serilog/reviewers-core any thoughts on this? Will merge to dev later today otherwise. Cheers!

@nblumhardt
Copy link
Member Author

Some changes:

  • Most values are now added to Scope, whether string, numeric, or formatted.
  • Those added via an IEnumerable<KeyValuePair<string,object>> are treated purely as properties.
  • There's no longer an opt-out; this can be reinstated if it's requested, but the benefits of opting out are unclear.
  • Everything always ends up on LogContext - including Scope.
  • An explicit .NET 4.6 TFM added, so that the more reliable AsyncLocal is used when available.

Test method:

using (_logger.BeginScope("Some name"))
using (_logger.BeginScope(42))
using (_logger.BeginScope("Formatted {WithValue}", 12345))
using (_logger.BeginScope(new Dictionary<string, object> { ["ViaDictionary"] = 100 }))
{
    _logger.LogInformation("Hello from the Index!");
}

Produces:

image

foreach (var stateProperty in stateProperties)
{
if (stateProperty.Key == SerilogLoggerProvider.OriginalFormatPropertyName && stateProperty.Value is string)
{
scopeItem = new ScalarValue(_state.ToString());
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will occur when _state is a FormattedLogValues object.

@@ -71,6 +83,10 @@ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
logEvent.AddPropertyIfAbsent(property);
}
}
else
{
scopeItem = propertyFactory.CreateProperty(NoName, _state).Value;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a shame we don't have CreatePropertyValue() here, to skip the extra allocation. We could special-case string to improve it a little.

@cilerler
Copy link

cilerler commented Nov 15, 2016

Do you think, you may also inject values in Dictionary into the Scope? That would be awesome.

I mean following line didn't appear in Scope which I believe it should

using (_logger.BeginScope(new Dictionary<string, object> { ["ViaDictionary"] = 100 }))

I know that the second parameter is object but still serialization to JSON would be 😎

@nblumhardt
Copy link
Member Author

Thanks for the feedback.

I'm hesitant to add the extra weight to each log event that this would entail. The Dictionary case is how correlation ids like OrderId, MessageId, CustomerId and so-on can be added to a sequence of events.

Adding a whole additional structured object to Scope in this scenario (as well as adding the scope property itself, for a start) will start to get expensive quickly.

@cilerler
Copy link

cilerler commented Nov 15, 2016

I hear you, and you are right. Thanks again! Is there a build that I can test?

@nblumhardt
Copy link
Member Author

Feeling pretty good about the direction here - let's get it through to dev so everyone can kick the tyres :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants