irontelemetry-dotnet/TelemetryExtensions.cs

186 lines
5.1 KiB
C#

using System.Diagnostics;
namespace IronTelemetry.Client;
/// <summary>
/// Extension methods for IronTelemetry integration.
/// </summary>
public static class TelemetryExtensions
{
/// <summary>
/// Configure global unhandled exception handling for console applications.
/// </summary>
public static void UseUnhandledExceptionHandler()
{
AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
{
if (args.ExceptionObject is Exception ex)
{
IronTelemetry.CaptureException(ex, ctx =>
ctx.WithExtra("isTerminating", args.IsTerminating)
.WithExtra("source", "UnhandledException"));
// Flush synchronously since the app may be terminating
IronTelemetry.Flush(TimeSpan.FromSeconds(2));
}
};
TaskScheduler.UnobservedTaskException += (sender, args) =>
{
IronTelemetry.CaptureException(args.Exception, ctx =>
ctx.WithExtra("source", "UnobservedTaskException"));
// Mark as observed to prevent app crash
args.SetObserved();
};
}
/// <summary>
/// Capture an exception and return it (for throw expressions).
/// </summary>
public static Exception Capture(this Exception ex)
{
IronTelemetry.CaptureException(ex);
return ex;
}
/// <summary>
/// Capture an exception with context and return it.
/// </summary>
public static Exception Capture(this Exception ex, Action<ExceptionContext> configure)
{
IronTelemetry.CaptureException(ex, configure);
return ex;
}
/// <summary>
/// Create a step scope that automatically tracks duration.
/// </summary>
public static StepScope TimeStep(this TelemetryClient client, string name, string? category = null)
{
return JourneyContext.StartStep(name, category);
}
/// <summary>
/// Execute an action within a tracked step.
/// </summary>
public static void TrackStep(string name, Action action, string? category = null)
{
using var step = IronTelemetry.StartStep(name, category);
try
{
action();
}
catch (Exception ex)
{
step.Fail(ex.Message);
throw;
}
}
/// <summary>
/// Execute an async action within a tracked step.
/// </summary>
public static async Task TrackStepAsync(string name, Func<Task> action, string? category = null)
{
using var step = IronTelemetry.StartStep(name, category);
try
{
await action();
}
catch (Exception ex)
{
step.Fail(ex.Message);
throw;
}
}
/// <summary>
/// Execute a function within a tracked step and return the result.
/// </summary>
public static T TrackStep<T>(string name, Func<T> func, string? category = null)
{
using var step = IronTelemetry.StartStep(name, category);
try
{
return func();
}
catch (Exception ex)
{
step.Fail(ex.Message);
throw;
}
}
/// <summary>
/// Execute an async function within a tracked step and return the result.
/// </summary>
public static async Task<T> TrackStepAsync<T>(string name, Func<Task<T>> func, string? category = null)
{
using var step = IronTelemetry.StartStep(name, category);
try
{
return await func();
}
catch (Exception ex)
{
step.Fail(ex.Message);
throw;
}
}
/// <summary>
/// Add Activity trace context to the current telemetry.
/// </summary>
public static ExceptionContext WithActivity(this ExceptionContext context, Activity? activity = null)
{
activity ??= Activity.Current;
if (activity != null)
{
context.TraceId = activity.TraceId.ToString();
context.SpanId = activity.SpanId.ToString();
}
return context;
}
/// <summary>
/// Execute a journey and return the result.
/// </summary>
public static T RunJourney<T>(string name, Func<T> action)
{
using var journey = IronTelemetry.StartJourney(name);
try
{
var result = action();
journey.Complete();
return result;
}
catch (Exception ex)
{
journey.Fail(ex.Message);
IronTelemetry.CaptureException(ex);
throw;
}
}
/// <summary>
/// Execute an async journey and return the result.
/// </summary>
public static async Task<T> RunJourneyAsync<T>(string name, Func<Task<T>> action)
{
using var journey = IronTelemetry.StartJourney(name);
try
{
var result = await action();
journey.Complete();
return result;
}
catch (Exception ex)
{
journey.Fail(ex.Message);
IronTelemetry.CaptureException(ex);
throw;
}
}
}