Last active
April 29, 2024 05:30
-
-
Save shirhatti/56c24a36d2c105493dab6e3527e62456 to your computer and use it in GitHub Desktop.
Consume ILogger logs through EventListener
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>net5.0</TargetFramework> | |
<Nullable>enable</Nullable> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="Microsoft.Extensions.Logging.EventSource" Version="5.0.0-preview.4.20251.6" /> | |
</ItemGroup> | |
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.Extensions.Logging; | |
using Microsoft.Extensions.Logging.EventSource; | |
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics.Tracing; | |
using System.Runtime.CompilerServices; | |
using System.Threading; | |
using System.Threading.Channels; | |
using System.Threading.Tasks; | |
namespace ConsoleApp4 | |
{ | |
public class Program | |
{ | |
static async Task Main(string[] args) | |
{ | |
var loggerFactory = LoggerFactory.Create(builder => | |
{ | |
builder.AddEventSourceLogger(); | |
}); | |
var logger = loggerFactory.CreateLogger<Program>(); | |
using var cts = new CancellationTokenSource(); | |
var token = cts.Token; | |
using var listener = new Listener(); | |
var listenerTask = Task.Run(async () => | |
{ | |
await foreach (var message in listener.FetchLogs(token)) | |
{ | |
Console.WriteLine(message); | |
} | |
}, token); | |
// A few sample logs messages | |
logger.LogInformation("Value is {val}", 0); | |
logger.LogInformation("Value is {val}", 0); | |
logger.LogInformation("Value is {val}", 0); | |
logger.LogInformation("Value is {val}", 0); | |
listener?.Dispose(); | |
await listenerTask; | |
} | |
internal class Listener : EventListener | |
{ | |
private bool _initialized = false; | |
private EventSource? _loggingEventSource; | |
private static readonly string LoggingEventSourceName = "Microsoft-Extensions-Logging"; | |
private const int _maxQueuedMessages = 10; | |
private readonly Channel<string> _channel = Channel.CreateBounded<string>(_maxQueuedMessages); | |
public Listener() | |
{ | |
Enable(); | |
_initialized = true; | |
} | |
private void Enable() | |
{ | |
if (_loggingEventSource != null) | |
{ | |
EnableEvents(_loggingEventSource, EventLevel.LogAlways, LoggingEventSource.Keywords.JsonMessage); | |
} | |
} | |
protected override void OnEventSourceCreated(EventSource eventSource) | |
{ | |
if (eventSource.Name == LoggingEventSourceName) | |
{ | |
_loggingEventSource = eventSource; | |
if (_initialized) | |
{ | |
Enable(); | |
} | |
} | |
} | |
protected override void OnEventWritten(EventWrittenEventArgs eventData) | |
{ | |
if (!_initialized) | |
{ | |
return; | |
} | |
if ((eventData.Payload?.Count) != 7) | |
{ | |
return; | |
} | |
if (eventData.Payload?[6] is string exceptionPayload) | |
{ | |
_ = _channel.Writer.TryWrite(exceptionPayload); | |
} | |
} | |
public async IAsyncEnumerable<string> FetchLogs([EnumeratorCancellation] CancellationToken token = default) | |
{ | |
while (await _channel.Reader.WaitToReadAsync(token)) | |
{ | |
var logMessage = await _channel.Reader.ReadAsync(token); | |
yield return logMessage; | |
} | |
} | |
public override void Dispose() | |
{ | |
_channel.Writer.TryComplete(); | |
base.Dispose(); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment