using Sentry; namespace Managing.Api.Exceptions; /// /// Utility class for capturing errors with Sentry across the application /// public static class SentryErrorCapture { /// /// Captures an exception in Sentry with additional context /// /// The exception to capture /// A descriptive name for where the error occurred /// Optional dictionary of additional data to include /// The Sentry event ID public static SentryId CaptureException(Exception exception, string contextName, IDictionary extraData = null) { return SentrySdk.CaptureException(exception, scope => { // Add context information scope.SetTag("context", contextName); scope.SetTag("error_type", exception.GetType().Name); // Add any extra data provided if (extraData != null) { foreach (var kvp in extraData) { scope.SetExtra(kvp.Key, kvp.Value?.ToString() ?? "null"); } } // Add extra info from the exception's Data dictionary if available foreach (var key in exception.Data.Keys) { if (key is string keyStr && exception.Data[key] != null) { scope.SetExtra($"exception_data_{keyStr}", exception.Data[key].ToString()); } } // Add a breadcrumb for context scope.AddBreadcrumb( message: $"Exception in {contextName}", category: "error", level: BreadcrumbLevel.Error ); }); } /// /// Enriches an exception with additional context data before throwing /// /// The exception to enrich /// Dictionary of context data to add /// The enriched exception for chaining public static Exception EnrichException(Exception exception, IDictionary contextData) { if (contextData != null) { foreach (var item in contextData) { exception.Data[item.Key] = item.Value; } } return exception; } /// /// Captures a message in Sentry with additional context /// /// The message to capture /// The severity level /// A descriptive name for where the message originated /// Optional dictionary of additional data to include /// The Sentry event ID public static SentryId CaptureMessage(string message, SentryLevel level, string contextName, IDictionary extraData = null) { // First capture the message with the specified level var id = SentrySdk.CaptureMessage(message, level); // Then add context via a scope SentrySdk.ConfigureScope(scope => { // Add context information scope.SetTag("context", contextName); // Add any extra data provided if (extraData != null) { foreach (var kvp in extraData) { scope.SetExtra(kvp.Key, kvp.Value?.ToString() ?? "null"); } } // Add a breadcrumb for context scope.AddBreadcrumb( message: $"Message from {contextName}", category: "message", level: BreadcrumbLevel.Info ); }); return id; } }