问题
I'm currently working on a .NET Standard 2.1 Blazor WebAssembly hosted application. I use Serilog with ElasticSearch and want to send log messages from my Client project to the ElasticSearch server. My project structure looks like this:
- BlazorApp.Client (I want to send logs to ElasticSearch from here)
- BlazorApp.Server
A similar question is asked here: Serilog Not Logging to ElasticSearch in Blazor WebAssembly
I figured out how to send Logs using Serilogs .WriteTo.ElasticSearch() but I always run into an error on my browser console: Cannot Wait on monitors
Elasticsearch.Net.UnexpectedElasticsearchClientException: Cannot wait on monitors on this runtime. ---> System.Threading.SynchronizationLockException: Cannot wait on monitors on this runtime.
Reproduce:
I currently run ElasticStack on my localhost (ports :9200, :5601). First I needed to activate CORS on my ElasticSearch server, because the Blazor WASm application is a static web application. Thus I added the following code to my elasticsearch.yml
:
http.cors.enabled : true
http.cors.allow-origin : "*"
http.cors.allow-methods : OPTIONS, HEAD, GET, POST, PUT, DELETE
http.cors.allow-headers : X-Requested-With,X-Auth-Token,Content-Type, Content-Length
Futher on, after doing some research on the the resulting errors in my browser console, I assumed that Serilogs NuGet Package Serilog.Sinks.Elasticsearch
might not be production ready yet.
The reason is, that .WriteTo.Elasticsearch()
is using an HttpClientHandler
which is only partially supported in current Blazor WASm - as far as I know.
Thus I had to write my own HttpClientHandler implementation for Blazor WASm:
public class WasmHttpClientHandler : HttpClientHandler
{
public override bool SupportsAutomaticDecompression => false;
public override bool SupportsProxy => false;
public override bool SupportsRedirectConfiguration => false;
}
The next step was to override the HttpConnection
class of the Serilog NuGet package:
public class WasmHttpConnection : HttpConnection
{
protected override HttpMessageHandler CreateHttpClientHandler(RequestData requestData)
{
var handler = new WasmHttpClientHandler();
Func<object, X509Certificate, X509Chain, SslPolicyErrors, bool> callback = requestData.ConnectionSettings?.ServerCertificateValidationCallback;
if (callback != null && handler.ServerCertificateCustomValidationCallback == null)
{
handler.ServerCertificateCustomValidationCallback = callback;
}
if (requestData.ClientCertificates != null)
{
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ClientCertificates.AddRange(requestData.ClientCertificates);
}
return handler;
}
}
Then I needed to use this new connection:
return new ElasticsearchSinkOptions(new Uri("http://localhost:9200"))
{
IndexFormat = "test-index",
Connection = new WasmHttpConnection(),
};
Main Method:
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.Enrich.WithExceptionDetails()
.WriteTo.Debug()
.WriteTo.Console(new CompactJsonFormatter())
.WriteTo.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://localhost:9200"))
{
IndexFormat = "test-index",
Connection = new WasmHttpConnection(),
})
.CreateLogger();
SelfLog.Enable(msg => Debug.WriteLine(msg));
With this setting, I can send my logs to my ElasticSearch and see the log messages in Kibana.
There is only one problem left, when I turn on Selflog on Serilog:
SelfLog.Enable(msg => Debug.WriteLine(msg));
I get the following error: Cannot wait on monitors.
Which is also discussed here: Blazor WebAssembly Monitor Threading exception
This means, the Serilog .WriteTo.Elasticsearch() might not be production ready for Blazor WASm. Or perhaps you have an idea on how to improve my solution?
Please let me know if you have any better idea, a suggest on how to improve this solution or even a better working solution!
来源:https://stackoverflow.com/questions/63408984/configure-serilog-elasticsearch-in-blazor-webassembly