{"action":"created","issue":{"url":"https://api.github.com/repos/serilog/serilog/issues/746","repository_url":"https://api.github.com/repos/serilog/serilog","labels_url":"https://api.github.com/repos/serilog/serilog/issues/746/labels{/name}","comments_url":"https://api.github.com/repos/serilog/serilog/issues/746/comments","events_url":"https://api.github.com/repos/serilog/serilog/issues/746/events","html_url":"https://github.com/serilog/serilog/issues/746","id":155925517,"number":746,"title":"Efficient creation of `LogEvent` with destructured properties","user":{"login":"nblumhardt","id":342712,"avatar_url":"https://avatars.githubusercontent.com/u/342712?v=3","gravatar_id":"","url":"https://api.github.com/users/nblumhardt","html_url":"https://github.com/nblumhardt","followers_url":"https://api.github.com/users/nblumhardt/followers","following_url":"https://api.github.com/users/nblumhardt/following{/other_user}","gists_url":"https://api.github.com/users/nblumhardt/gists{/gist_id}","starred_url":"https://api.github.com/users/nblumhardt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nblumhardt/subscriptions","organizations_url":"https://api.github.com/users/nblumhardt/orgs","repos_url":"https://api.github.com/users/nblumhardt/repos","events_url":"https://api.github.com/users/nblumhardt/events{/privacy}","received_events_url":"https://api.github.com/users/nblumhardt/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/serilog/serilog/labels/core","name":"core","color":"009800"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/serilog/serilog/milestones/11","html_url":"https://github.com/serilog/serilog/milestones/2.0.0-beta1","labels_url":"https://api.github.com/repos/serilog/serilog/milestones/11/labels","id":1263535,"number":11,"title":"2.0.0-beta1","description":"","creator":{"login":"nblumhardt","id":342712,"avatar_url":"https://avatars.githubusercontent.com/u/342712?v=3","gravatar_id":"","url":"https://api.github.com/users/nblumhardt","html_url":"https://github.com/nblumhardt","followers_url":"https://api.github.com/users/nblumhardt/followers","following_url":"https://api.github.com/users/nblumhardt/following{/other_user}","gists_url":"https://api.github.com/users/nblumhardt/gists{/gist_id}","starred_url":"https://api.github.com/users/nblumhardt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nblumhardt/subscriptions","organizations_url":"https://api.github.com/users/nblumhardt/orgs","repos_url":"https://api.github.com/users/nblumhardt/repos","events_url":"https://api.github.com/users/nblumhardt/events{/privacy}","received_events_url":"https://api.github.com/users/nblumhardt/received_events","type":"User","site_admin":false},"open_issues":2,"closed_issues":13,"state":"open","created_at":"2015-08-19T21:46:13Z","updated_at":"2016-05-20T09:45:43Z","due_on":null,"closed_at":null},"comments":1,"created_at":"2016-05-20T09:45:40Z","updated_at":"2016-05-20T10:07:01Z","closed_at":null,"body":"A longtime API rough spot: it's non-trivial to construct a `LogEvent` from its constituent parts except by calling a method on an `ILogger`.\r\n\r\nIt's not _impossible_, but there are two complications:\r\n\r\n - Parsing and binding parameters to a `MessageTemplate` isn't straightforward\r\n - Properties not in the template can only be added through `ForContext()`, which is indirect and not super-efficient\r\n\r\nThe current state of things is summed up pretty well by this method from _Serilog.Extensions.Logging_, which takes a payload from a _Microsoft.Extensions.Logging_ call and passes it through to the Serilog pipeline:\r\n\r\nhttps://github.com/serilog/serilog-extensions-logging/blob/dev/src/Serilog.Extensions.Logging/Extensions/Logging/SerilogLogger.cs#L51\r\n\r\nIn there you'll observe a lot of.\r\n\r\n```csharp\r\nlogger = logger.ForContext(property.Key, property.Value);\r\n```\r\n\r\nThis pattern takes a name/value pair and attaches them as a property by way of enrichment. It's not correct to just call `new LogEventProperty(name, new ScalarValue(value))`, since policies may be in effect for which types are captured as scalar values. (When destructuring is required this is especially true.)\r\n\r\nThe issue of binding a `MessageTemplate` is side-stepped because the positional mapping is already done by the external logging API, but it's still unfortunate that template parsing in this class can't make use of the internal cache shared by Serilog loggers.\r\n\r\nI have one proposal to offer but there are several ways to approach it so this thread is open for ideas :-)\r\n"},"comment":{"url":"https://api.github.com/repos/serilog/serilog/issues/comments/220567313","html_url":"https://github.com/serilog/serilog/issues/746#issuecomment-220567313","issue_url":"https://api.github.com/repos/serilog/serilog/issues/746","id":220567313,"user":{"login":"nblumhardt","id":342712,"avatar_url":"https://avatars.githubusercontent.com/u/342712?v=3","gravatar_id":"","url":"https://api.github.com/users/nblumhardt","html_url":"https://github.com/nblumhardt","followers_url":"https://api.github.com/users/nblumhardt/followers","following_url":"https://api.github.com/users/nblumhardt/following{/other_user}","gists_url":"https://api.github.com/users/nblumhardt/gists{/gist_id}","starred_url":"https://api.github.com/users/nblumhardt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nblumhardt/subscriptions","organizations_url":"https://api.github.com/users/nblumhardt/orgs","repos_url":"https://api.github.com/users/nblumhardt/repos","events_url":"https://api.github.com/users/nblumhardt/events{/privacy}","received_events_url":"https://api.github.com/users/nblumhardt/received_events","type":"User","site_admin":false},"created_at":"2016-05-20T10:07:01Z","updated_at":"2016-05-20T10:07:01Z","body":"### Proposal 1\r\n\r\n```csharp\r\nvar evt = logger.CreateEvent(\r\n    DateTimeOffset.Now, level, exception, \"Some {Number}\", 42);\r\n\r\nevt.AddOrUpdateProperty(\r\n    logger.CreateProperty(\"Ticks\", 123));\r\n\r\nevt.AddOrUpdateProperty(\r\n    logger.CreateProperty(\"User\", user, destructureObjects: true));\r\n\r\nlogger.Write(evt);\r\n```\r\n\r\n - `CreateEvent()` parses the message template and binds parameters (invoking destructuring policies etc. as needed)\r\n - `CreateProperty()` just handles the scalar conversion/destructuring duties.\r\n\r\nIt's not an incredibly elegant interface, lots of long method names - but this kind of thing is only used in glue code, not typical application code.\r\n\r\n#### Issues/questions\r\n\r\nFirst, it's a breaking change for the `ILogger` interface. At this point very few 2.0-compatible packages will _implement_ `ILogger`, so it's the last opportunity to get this change in, I think. If we make this change we should also do #585.\r\n\r\nThe _Serilog.Extensions.Logging_ code above could not use `CreateEvent()` as proposed, since the binding logic generates warnings when template \"holes\" don't have corresponding values. Because of this, the standalone `MessageTemplateParser` would still be needed. A workaround to benefit from caching might just be to grab a copy of the one from the Serilog source, so maybe a non-issue.\r\n\r\nFinally, it's worth noting that the names don't conflict on first character with anything in `ILogger`, but if we decided to add symmetric versions to `Log` then `Create***()` will have a first-char collision with `CloseAndFlush()`. This could be avoided by simply requiring callers to use `Log.Logger.Create***()`, we might come up with an alternative name, or given the infrequent use of both the factory methods and `CloseAndFlush()`, we might not care."}}
{"actor":{"display_login":"nblumhardt"}}