From 08cca038b747637052496a0906d93b647cc5010c Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Fri, 27 Jun 2025 21:49:27 +0200 Subject: [PATCH 1/2] fix/test fallback serilog (#523) - Test fallback - update - Ensure fallback mechanism works with the latest ingest-dotnet (cherry picked from commit a4c06a5fc31a3472d8b5caa4c1f71bec35bc83bc) --- ...c.Ingest.Elasticsearch.CommonSchema.csproj | 2 +- .../ElasticsearchSink.cs | 13 +++-- .../Elasticsearch.IntegrationDefaults.csproj | 2 +- .../Elastic.Serilog.Sinks.Tests.csproj | 2 + .../SerilogFailureOutputTests.cs | 54 +++++++++++++++++++ 5 files changed, 66 insertions(+), 7 deletions(-) create mode 100644 tests/Elastic.Serilog.Sinks.Tests/SerilogFailureOutputTests.cs diff --git a/src/Elastic.Ingest.Elasticsearch.CommonSchema/Elastic.Ingest.Elasticsearch.CommonSchema.csproj b/src/Elastic.Ingest.Elasticsearch.CommonSchema/Elastic.Ingest.Elasticsearch.CommonSchema.csproj index 77b65e53..1787e90a 100644 --- a/src/Elastic.Ingest.Elasticsearch.CommonSchema/Elastic.Ingest.Elasticsearch.CommonSchema.csproj +++ b/src/Elastic.Ingest.Elasticsearch.CommonSchema/Elastic.Ingest.Elasticsearch.CommonSchema.csproj @@ -10,7 +10,7 @@ - + diff --git a/src/Elastic.Serilog.Sinks/ElasticsearchSink.cs b/src/Elastic.Serilog.Sinks/ElasticsearchSink.cs index a6592405..4aa0c0e7 100644 --- a/src/Elastic.Serilog.Sinks/ElasticsearchSink.cs +++ b/src/Elastic.Serilog.Sinks/ElasticsearchSink.cs @@ -31,14 +31,14 @@ public interface IElasticsearchSinkOptions IEcsTextFormatterConfiguration EcsTextFormatterConfiguration { get; } /// - public DataStreamName DataStream { get; } + DataStreamName DataStream { get; } /// /// The ILM Policy to apply, see the following for more details: /// https://www.elastic.co/guide/en/elasticsearch/reference/current/index-lifecycle-management.html /// Defaults to `logs` which is shipped by default with Elasticsearch /// - public string? IlmPolicy { get; } + string? IlmPolicy { get; } } @@ -136,8 +136,11 @@ public ElasticsearchSink(ElasticsearchSinkOptions options) var channelOptions = new DataStreamChannelOptions(options.Transport) { DataStream = options.DataStream, - ExportMaxRetriesCallback = EmitExportFailures + ExportMaxRetriesCallback = EmitExportFailures, + ExportExceptionCallback = _ => + { + } }; options.ConfigureChannel?.Invoke(channelOptions); _channel = new EcsDataStreamChannel(channelOptions, new [] { new SelfLogCallbackListener(options)}); @@ -153,7 +156,7 @@ private void EmitExportFailures(IReadOnlyCollection documents) .ToArray(); _failureListener.OnLoggingFailed( this, - LoggingFailureKind.Temporary, + LoggingFailureKind.Permanent, "Failure to export events over to Elasticsearch.", logs, exception: null @@ -169,7 +172,7 @@ public void Emit(LogEvent logEvent) { _failureListener.OnLoggingFailed( this, - LoggingFailureKind.Temporary, + LoggingFailureKind.Permanent, "Failure to push event over the channel.", [logEvent], exception: null diff --git a/tests-integration/Elasticsearch.IntegrationDefaults/Elasticsearch.IntegrationDefaults.csproj b/tests-integration/Elasticsearch.IntegrationDefaults/Elasticsearch.IntegrationDefaults.csproj index 80c23f6b..7b48b1a4 100644 --- a/tests-integration/Elasticsearch.IntegrationDefaults/Elasticsearch.IntegrationDefaults.csproj +++ b/tests-integration/Elasticsearch.IntegrationDefaults/Elasticsearch.IntegrationDefaults.csproj @@ -11,7 +11,7 @@ - + diff --git a/tests/Elastic.Serilog.Sinks.Tests/Elastic.Serilog.Sinks.Tests.csproj b/tests/Elastic.Serilog.Sinks.Tests/Elastic.Serilog.Sinks.Tests.csproj index 7ccd2cd7..158fe856 100644 --- a/tests/Elastic.Serilog.Sinks.Tests/Elastic.Serilog.Sinks.Tests.csproj +++ b/tests/Elastic.Serilog.Sinks.Tests/Elastic.Serilog.Sinks.Tests.csproj @@ -12,6 +12,8 @@ + + diff --git a/tests/Elastic.Serilog.Sinks.Tests/SerilogFailureOutputTests.cs b/tests/Elastic.Serilog.Sinks.Tests/SerilogFailureOutputTests.cs new file mode 100644 index 00000000..a239ab35 --- /dev/null +++ b/tests/Elastic.Serilog.Sinks.Tests/SerilogFailureOutputTests.cs @@ -0,0 +1,54 @@ +using Elastic.Channels; +using Elastic.Channels.Diagnostics; +using Elastic.Transport; +using FluentAssertions; +using Serilog; +using Serilog.Sinks.TestCorrelator; +using Xunit; +using DataStreamName = Elastic.Ingest.Elasticsearch.DataStreams.DataStreamName; + +namespace Elastic.Serilog.Sinks.Tests +{ + public class SerilogFailureOutputTests + { + private readonly CountdownEvent _waitHandle; + private IChannelDiagnosticsListener? _listener; + private ElasticsearchSinkOptions SinkOptions { get; } + + public SerilogFailureOutputTests() + { + _waitHandle = new CountdownEvent(1); + SinkOptions = new ElasticsearchSinkOptions(new DistributedTransport(new TransportConfiguration())) + { + DataStream = new DataStreamName("logs", "serilog", "tests"), + ConfigureChannel = c => + { + c.BufferOptions = new BufferOptions + { + ExportMaxRetries = 0, + WaitHandle = _waitHandle, + OutboundBufferMaxSize = 1 + }; + }, + ChannelDiagnosticsCallback = (l) => _listener = l + }; + } + + [Fact] public void AssertLogs() + { + var loggerConfig = new LoggerConfiguration() + .MinimumLevel.Information() + .WriteTo.FallbackChain( + fc => fc.Elasticsearch(SinkOptions), + fc => fc.Console() + ); + + using var logger = loggerConfig.CreateLogger(); + logger.Information("Hello world"); + + if (!_waitHandle.WaitHandle.WaitOne(TimeSpan.FromSeconds(10))) + throw new Exception($"No flush occurred in 10 seconds: {_listener}", _listener?.ObservedException); + + } + } +} From 46ccc56c3d58a83514381d1235c164ed89f2c841 Mon Sep 17 00:00:00 2001 From: Martijn Laarman Date: Mon, 28 Jul 2025 17:29:24 +0200 Subject: [PATCH 2/2] remove empty handler --- src/Elastic.Serilog.Sinks/ElasticsearchSink.cs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Elastic.Serilog.Sinks/ElasticsearchSink.cs b/src/Elastic.Serilog.Sinks/ElasticsearchSink.cs index 4aa0c0e7..9d83f7eb 100644 --- a/src/Elastic.Serilog.Sinks/ElasticsearchSink.cs +++ b/src/Elastic.Serilog.Sinks/ElasticsearchSink.cs @@ -136,11 +136,7 @@ public ElasticsearchSink(ElasticsearchSinkOptions options) var channelOptions = new DataStreamChannelOptions(options.Transport) { DataStream = options.DataStream, - ExportMaxRetriesCallback = EmitExportFailures, - ExportExceptionCallback = _ => - { - - } + ExportMaxRetriesCallback = EmitExportFailures }; options.ConfigureChannel?.Invoke(channelOptions); _channel = new EcsDataStreamChannel(channelOptions, new [] { new SelfLogCallbackListener(options)});