irontelemetry-dotnet/IronTelemetry.cs

232 lines
6.5 KiB
C#

namespace IronTelemetry.Client;
/// <summary>
/// Static API for IronTelemetry.
/// Level 0: Drop-in error capture (Init + CaptureException)
/// Level 1: Ambient journey correlation (StartJourney + StartStep)
/// </summary>
public static class IronTelemetry
{
private static TelemetryClient? _client;
private static readonly object _lock = new();
/// <summary>
/// Initialize IronTelemetry with a DSN.
/// </summary>
public static void Init(string dsn)
{
Init(new TelemetryOptions { Dsn = dsn });
}
/// <summary>
/// Initialize IronTelemetry with options.
/// </summary>
public static void Init(TelemetryOptions options)
{
lock (_lock)
{
_client = new TelemetryClient(options);
}
}
#region Level 0 - Exception Capture
/// <summary>
/// Capture an exception and send it to IronTelemetry.
/// Automatically correlates with current journey if one exists.
/// </summary>
public static void CaptureException(Exception ex)
{
EnsureInitialized();
_client!.CaptureException(ex);
}
/// <summary>
/// Capture an exception with additional context.
/// </summary>
public static void CaptureException(Exception ex, Action<ExceptionContext> configure)
{
EnsureInitialized();
var context = new ExceptionContext();
configure(context);
_client!.CaptureException(ex, context);
}
/// <summary>
/// Capture a message.
/// </summary>
public static void CaptureMessage(string message, TelemetryLevel level = TelemetryLevel.Info)
{
EnsureInitialized();
_client!.CaptureMessage(message, level);
}
/// <summary>
/// Add a breadcrumb to the current context.
/// </summary>
public static void AddBreadcrumb(string message, string? category = null)
{
EnsureInitialized();
_client!.AddBreadcrumb(new Breadcrumb
{
Message = message,
Category = category ?? "default",
Level = BreadcrumbLevel.Info,
Timestamp = DateTime.UtcNow
});
}
/// <summary>
/// Add a breadcrumb to the current context.
/// </summary>
public static void AddBreadcrumb(Breadcrumb breadcrumb)
{
EnsureInitialized();
_client!.AddBreadcrumb(breadcrumb);
}
/// <summary>
/// Set the current user context.
/// </summary>
public static void SetUser(string? id, string? email = null, string? username = null)
{
EnsureInitialized();
_client!.SetUser(id, email, username);
}
/// <summary>
/// Set a global tag that will be sent with all events.
/// </summary>
public static void SetTag(string key, string value)
{
EnsureInitialized();
_client!.SetTag(key, value);
}
/// <summary>
/// Set extra data that will be sent with all events.
/// </summary>
public static void SetExtra(string key, object value)
{
EnsureInitialized();
_client!.SetExtra(key, value);
}
#endregion
#region Level 1 - Journey Correlation
/// <summary>
/// Start a new journey. All telemetry within this scope will be correlated.
/// </summary>
/// <param name="name">The journey name (e.g., "Checkout Flow", "User Onboarding")</param>
/// <returns>A disposable scope - dispose to end the journey</returns>
/// <example>
/// using (IronTelemetry.StartJourney("Checkout Flow"))
/// {
/// IronTelemetry.SetUser(currentUser.Id);
///
/// using (IronTelemetry.StartStep("Validate Cart", "business"))
/// {
/// ValidateCart();
/// }
///
/// using (IronTelemetry.StartStep("Process Payment", "business"))
/// {
/// ProcessPayment();
/// }
/// }
/// </example>
public static JourneyScope StartJourney(string name)
{
EnsureInitialized();
return JourneyContext.StartJourney(name);
}
/// <summary>
/// Start a step within the current journey.
/// If no journey exists, one is created automatically.
/// </summary>
/// <param name="name">The step name (e.g., "Validate Cart", "Process Payment")</param>
/// <param name="category">Optional category (e.g., "business", "technical", "navigation")</param>
/// <returns>A disposable scope - dispose to end the step</returns>
public static StepScope StartStep(string name, string? category = null)
{
EnsureInitialized();
return JourneyContext.StartStep(name, category);
}
/// <summary>
/// Gets the current journey, if any.
/// </summary>
public static JourneyScope? CurrentJourney => JourneyContext.Current;
/// <summary>
/// Gets the current step, if any.
/// </summary>
public static StepScope? CurrentStep => JourneyContext.CurrentStep;
/// <summary>
/// Gets the current journey ID, if any.
/// </summary>
public static string? CurrentJourneyId => JourneyContext.CurrentJourneyId;
/// <summary>
/// Set metadata on the current journey.
/// </summary>
public static void SetJourneyMetadata(string key, object value)
{
JourneyContext.SetMetadata(key, value);
}
/// <summary>
/// Mark the current step as failed.
/// </summary>
public static void FailCurrentStep(string? reason = null)
{
JourneyContext.FailCurrentStep(reason);
}
#endregion
#region Flush
/// <summary>
/// Flush any pending events synchronously.
/// </summary>
public static void Flush(TimeSpan? timeout = null)
{
_client?.Flush(timeout ?? TimeSpan.FromSeconds(5));
}
/// <summary>
/// Flush any pending events asynchronously.
/// </summary>
public static Task FlushAsync(TimeSpan? timeout = null)
{
return _client?.FlushAsync(timeout ?? TimeSpan.FromSeconds(5)) ?? Task.CompletedTask;
}
#endregion
/// <summary>
/// Get whether the SDK is initialized.
/// </summary>
public static bool IsInitialized => _client != null;
/// <summary>
/// Get the underlying TelemetryClient instance.
/// Returns null if not initialized.
/// </summary>
public static TelemetryClient? Client => _client;
private static void EnsureInitialized()
{
if (_client == null)
{
throw new InvalidOperationException(
"IronTelemetry has not been initialized. Call IronTelemetry.Init() first.");
}
}
}