108 lines
3.9 KiB
C#
108 lines
3.9 KiB
C#
using EonaCat.LogStack.Core;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace EonaCat.LogStack.Flows
|
|
{
|
|
// This file is part of the EonaCat project(s) which is released under the Apache License.
|
|
// See the LICENSE file or go to https://EonaCat.com/License for full license details.
|
|
|
|
/// <summary>
|
|
/// A flow that transforms log events before passing them to an inner flow.
|
|
/// Allows modification of messages, properties, and other attributes.
|
|
/// </summary>
|
|
public sealed class TransformFlow : FlowBase
|
|
{
|
|
private readonly IFlow _innerFlow;
|
|
private readonly Func<LogEvent, LogEvent> _transformer;
|
|
|
|
public TransformFlow(
|
|
IFlow innerFlow,
|
|
Func<LogEvent, LogEvent> transformer,
|
|
LogLevel minimumLevel = LogLevel.Trace)
|
|
: base(innerFlow?.Name + "_Transform" ?? "TransformFlow", minimumLevel)
|
|
{
|
|
_innerFlow = innerFlow ?? throw new ArgumentNullException(nameof(innerFlow));
|
|
_transformer = transformer ?? throw new ArgumentNullException(nameof(transformer));
|
|
}
|
|
|
|
public override async Task<WriteResult> BlastAsync(LogEvent logEvent, CancellationToken cancellationToken = default)
|
|
{
|
|
if (!IsEnabled || !IsLogLevelEnabled(logEvent))
|
|
{
|
|
return WriteResult.LevelFiltered;
|
|
}
|
|
|
|
try
|
|
{
|
|
var transformedEvent = _transformer(logEvent);
|
|
var result = await _innerFlow.BlastAsync(transformedEvent, cancellationToken).ConfigureAwait(false);
|
|
if (result == WriteResult.Success)
|
|
{
|
|
Interlocked.Increment(ref BlastedCount);
|
|
}
|
|
else
|
|
{
|
|
Interlocked.Increment(ref DroppedCount);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Interlocked.Increment(ref DroppedCount);
|
|
System.Diagnostics.Debug.WriteLine($"TransformFlow error: {ex.Message}");
|
|
return WriteResult.Failed;
|
|
}
|
|
}
|
|
|
|
public override async Task<WriteResult> BlastBatchAsync(ReadOnlyMemory<LogEvent> logEvents, CancellationToken cancellationToken = default)
|
|
{
|
|
if (!IsEnabled)
|
|
{
|
|
return WriteResult.FlowDisabled;
|
|
}
|
|
|
|
var eventsArray = logEvents.ToArray();
|
|
var transformedEvents = new List<LogEvent>();
|
|
foreach (var logEvent in eventsArray)
|
|
{
|
|
if (IsLogLevelEnabled(logEvent))
|
|
{
|
|
try
|
|
{
|
|
var transformed = _transformer(logEvent);
|
|
transformedEvents.Add(transformed);
|
|
Interlocked.Increment(ref BlastedCount);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Interlocked.Increment(ref DroppedCount);
|
|
System.Diagnostics.Debug.WriteLine($"TransformFlow batch error: {ex.Message}");
|
|
}
|
|
}
|
|
}
|
|
|
|
if (transformedEvents.Count > 0)
|
|
{
|
|
return await _innerFlow.BlastBatchAsync(transformedEvents.ToArray(), cancellationToken).ConfigureAwait(false);
|
|
}
|
|
|
|
return WriteResult.Success;
|
|
}
|
|
|
|
public override async Task FlushAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
await _innerFlow.FlushAsync(cancellationToken).ConfigureAwait(false);
|
|
}
|
|
|
|
public override async ValueTask DisposeAsync()
|
|
{
|
|
await _innerFlow.DisposeAsync().ConfigureAwait(false);
|
|
await base.DisposeAsync().ConfigureAwait(false);
|
|
}
|
|
}
|
|
}
|