Reputation: 6518
I am trying out for the first time Serilog, and I am having trouble understanding how it parses data during serialization. I am using Serilog.Sinks.Http in order to pass exception information from Client (Blazor wazm hosted) to Server (ASP.NET Core 6.0).
The way I understood it, Serilog.AspNetCore can only be used on the server side, which I was able to configure successfully. However, on client side I need a library that can serialize through HTTP.
So I found Serilog.Sinks.Http. First I experienced a problem on the Serilog registration part: I could not find a way to insert a Serilog provider on the client side, as I was able on the server side. That means that on server side Serilog is nicely integrated into MS Logging infrastructure, and on the client it is not. I was only able to register it in DI container. But it is completely disconnected from MS logging framework. So, two questions:
Q1) Is it possible to register Serilog as a custom provider in a blazor wasm hosted project, so that it can integrate with MS framework? This is the code I have now:
builder.Logging.Services.AddScoped<Serilog.ILogger>(_ =>
new LoggerConfiguration()
.WriteTo.Http(requestUri: uri)
.CreateLogger()
.ForContext<Program>());
Q2) How can I control the serialization part? Basically what I am interested in, is to either pass a whole exception object with some additional data, or pass my custom entity, and then log this entity on the server side. I know I can establish connection with normal web api call, but as far as I understand, Serilog has advanced buffering system, where it is able to store messages and then resend them when connection is reactivated, for example.
I tried something like this:
Logger.Error( exception, someMessage);
Then I get a weird JSON structure on the Server side, I do not know what to do with it. Here is an example where I throw AccessViolationException. I recognize the first #events# part, I have seen it in some example on the github, where they used LogEvents for mapping:
public class LogEvents { public LogEvent[] Events { get; set; } = null!; }
But I just could not make it to work with my custom object (more data):
{{
"events": [
{
"Timestamp": "2021-12-20T19:04:25.822+01:00",
"Level": "Error",
"MessageTemplate": "Exception while bla bla bla",
"RenderedMessage": "Exception while bla bla bla",
"Exception": "System.AccessViolationException: bla bla at bla bla",
"Properties": {
"SourceContext": "Program"
}
}
]
}}
ChildrenTokens: Count = 1
Count: 1
First: {"events": [
{
"Timestamp": "2021-12-20T19:04:25.822+01:00",
"Level": "Error",
"MessageTemplate": "Exception while bla bla bla",
"RenderedMessage": "Exception while bla bla bla",
"Exception": "System.AccessViolationException: bla bla at bla bla",
"Properties": {
"SourceContext": "Program"
}
}
]}
HasValues: true
Last: {"events": [
{
"Timestamp": "2021-12-20T19:04:25.822+01:00",
"Level": "Error",
"MessageTemplate": "Exception while bla bla bla",
"RenderedMessage": "Exception while bla bla bla",
"Exception": "System.AccessViolationException: bla bla at bla bla",
"Properties": {
"SourceContext": "Program"
}
}
]}
Next: null
Parent: null
Path: ""
Previous: null
Root: {{
"events": [
{
"Timestamp": "2021-12-20T19:04:25.822+01:00",
"Level": "Error",
"MessageTemplate": "Exception while bla bla bla",
"RenderedMessage": "Exception while bla bla bla",
"Exception": "System.AccessViolationException: bla bla at bla bla",
"Properties": {
"SourceContext": "Program"
}
}
]
}}
Type: Object
Results View: Expanding the Results View will enumerate the IEnumerable
Dynamic View: Expanding the Dynamic View will get the dynamic members for the object
Upvotes: 1
Views: 2252
Reputation: 341
In order to get Blazor WASM client Serilog information passed to the server for processing I followed https://nblumhardt.com/2019/11/serilog-blazor/ which uses Serilog.Sinks.BrowserHttp and Serilog.AspNetCore.Ingestion which are both pre-release Nuget packages.
As per a comment on that link, I also found it necessary to supply the endpointUrl parameter as:
.WriteTo.BrowserHttp(endpointUrl: builder.HostEnvironment.BaseAddress+"ingest"
In the client Program.cs
var levelSwitch = new LoggingLevelSwitch();
string LogTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u3}] {Message,-120:j} {NewLine}{Exception}";
Log.Logger = new LoggerConfiguration()
.MinimumLevel.ControlledBy(levelSwitch)
.Enrich.WithProperty("InstanceId", Guid.NewGuid().ToString("n"))
.WriteTo.BrowserHttp(endpointUrl: builder.HostEnvironment.BaseAddress + "ingest", controlLevelSwitch: levelSwitch)
.WriteTo.BrowserConsole(outputTemplate: LogTemplate)
.CreateLogger();
In the server Program.cs
app.UseSerilogIngestion();
app.UseSerilogRequestLogging();
It works with .NET6.
Upvotes: 2