using System.Diagnostics;
using MessageFlow;
namespace MessageFlow.Samples;
///
/// Shows the built-in logging and tracing middleware, UseLogging and UseTracing.
///
public static class DiagnosticsSample
{
///
/// Builds a chain observed by a logger and by an per request.
///
/// Receives one entry per request.
/// The composed chain.
public static IChain BuildChain(IChainLogger logger)
{
ArgumentNullException.ThrowIfNull(logger);
return Chain.Create()
.UseLogging(logger, ChainLogLevel.Information)
.UseTracing("MessageFlow.Samples.Diagnostics")
.UseWhen(
request => request.StartsWith("ping", StringComparison.OrdinalIgnoreCase),
(_, _) => new ValueTask("pong"))
.WithFallback((request, _) => new ValueTask($"echo: {request}"))
.Build();
}
///
/// Runs the sample with a listener subscribed to the library activity source.
///
/// The writer receiving the sample output.
/// A token used to cancel the operation.
/// The log entries produced by the requests.
public static async Task> RunAsync(
TextWriter output,
CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(output);
var logger = new CollectingChainLogger();
var activityNames = new List();
using var listener = new ActivityListener
{
ShouldListenTo = source => source.Name == ChainDiagnostics.ActivitySourceName,
Sample = (ref ActivityCreationOptions _) => ActivitySamplingResult.AllDataAndRecorded,
ActivityStopped = activity => activityNames.Add($"{activity.OperationName}:{activity.Status}"),
};
ActivitySource.AddActivityListener(listener);
var chain = BuildChain(logger);
foreach (var request in new[] { "ping", "hello" })
{
var response = await chain.ExecuteAsync(request, cancellationToken).ConfigureAwait(false);
await output.WriteLineAsync($"{request} => {response}").ConfigureAwait(false);
}
foreach (var entry in logger.Entries)
{
await output.WriteLineAsync($" log: {entry}").ConfigureAwait(false);
}
foreach (var activity in activityNames)
{
await output.WriteLineAsync($" activity: {activity}").ConfigureAwait(false);
}
return logger.Entries;
}
///
/// A minimal collecting the formatted entries in memory.
///
private sealed class CollectingChainLogger : IChainLogger
{
public List Entries { get; } = [];
public bool IsEnabled(ChainLogLevel level) => level >= ChainLogLevel.Information;
public void Log(ChainLogLevel level, string message, Exception? exception)
=> Entries.Add($"{level}: {message}");
}
}