protected override void ProcessException( SpecialException exception, SentryEvent sentryEvent) { sentryEvent.AddBreadcrumb("Processor running on special exception."); sentryEvent.SetTag("IsSpecial", exception.IsSpecial.ToString()); }
public SentryEvent Process(SentryEvent @event) { // Here you can modify the event as you need if (@event.Level > SentryLevel.Info) { @event.AddBreadcrumb("Processed by " + nameof(SomeEventProcessor)); } return(@event); }
public SentryEvent Process(SentryEvent @event) { // Here you can modify the event as you need if (@event.Level > SentryLevel.Info) { @event.AddBreadcrumb("Processed by " + nameof(SomeEventProcessor)); @event.User = new User { Username = Environment.UserName }; @event.ServerName = Environment.MachineName; } return(@event); }
public void SerializeObject_AllPropertiesSetToNonDefault_SerializesValidObject() { var ex = new Exception("exception message"); var timestamp = DateTimeOffset.MaxValue; var id = Guid.Parse("4b780f4c-ec03-42a7-8ef8-a41c9d5621f8"); var sut = new SentryEvent(ex, timestamp, id) { User = new User { Id = "user-id" }, Request = new Request { Method = "POST" }, Contexts = new Contexts { ["context_key"] = "context_value", [".NET Framework"] = new Dictionary <string, string> { [".NET Framework"] = "\"v2.0.50727\", \"v3.0\", \"v3.5\"", [".NET Framework Client"] = "\"v4.8\", \"v4.0.0.0\"", [".NET Framework Full"] = "\"v4.8\"" } }, Sdk = new SdkVersion { Name = "SDK-test", Version = "1.1.1" }, Environment = "environment", Level = SentryLevel.Fatal, Logger = "logger", Message = new SentryMessage { Message = "message", Formatted = "structured_message" }, Modules = { { "module_key", "module_value" } }, Release = "release", SentryExceptions = new[] { new SentryException { Value = "exception_value" } }, SentryThreads = new[] { new SentryThread { Crashed = true } }, ServerName = "server_name", TransactionName = "transaction", }; sut.Sdk.AddPackage(new Package("name", "version")); sut.AddBreadcrumb(new Breadcrumb(timestamp, "crumb")); sut.AddBreadcrumb(new Breadcrumb( timestamp, "message", "type", new Dictionary <string, string> { { "data-key", "data-value" } }, "category", BreadcrumbLevel.Warning)); sut.SetExtra("extra_key", "extra_value"); sut.Fingerprint = new[] { "fingerprint" }; sut.SetTag("tag_key", "tag_value"); var actualString = sut.ToJsonString(); var actual = SentryEvent.FromJson(Json.Parse(actualString)); actual.Should().BeEquivalentTo(sut, o => { // Due to timestamp precision o.Excluding(e => e.Breadcrumbs); o.Excluding(e => e.Exception); return(o); }); // Expected item[0].Timestamp to be <9999-12-31 23:59:59.9999999>, but found <9999-12-31 23:59:59.999>. actual.Breadcrumbs.Should().BeEquivalentTo(sut.Breadcrumbs, o => o.Excluding(b => b.Timestamp)); var counter = 0; foreach (var sutBreadcrumb in sut.Breadcrumbs) { sutBreadcrumb.Timestamp.Should().BeCloseTo(actual.Breadcrumbs.ElementAt(counter++).Timestamp); } }
public void SerializeObject_AllPropertiesSetToNonDefault_SerializesValidObject() { var ex = new Exception("exception message"); var timestamp = DateTimeOffset.MaxValue; var id = Guid.Parse("4b780f4c-ec03-42a7-8ef8-a41c9d5621f8"); var sut = new SentryEvent(ex, timestamp, id) { User = new User { Id = "user-id" }, Request = new Request { Method = "POST" }, Contexts = new Contexts { ["context_key"] = "context_value", [".NET Framework"] = new Dictionary <string, string> { [".NET Framework"] = "\"v2.0.50727\", \"v3.0\", \"v3.5\"", [".NET Framework Client"] = "\"v4.8\", \"v4.0.0.0\"", [".NET Framework Full"] = "\"v4.8\"" } }, Sdk = new SdkVersion { Name = "SDK-test", Version = "1.1.1" }, Environment = "environment", Level = SentryLevel.Fatal, Logger = "logger", Message = new SentryMessage { Message = "message", Formatted = "structured_message" }, Modules = { { "module_key", "module_value" } }, Release = "release", SentryExceptions = new[] { new SentryException { Value = "exception_value" } }, SentryThreads = new[] { new SentryThread { Crashed = true } }, ServerName = "server_name", TransactionName = "transaction", }; sut.Sdk.AddPackage(new Package("name", "version")); sut.AddBreadcrumb(new Breadcrumb(timestamp, "crumb")); sut.AddBreadcrumb(new Breadcrumb( timestamp, "message", "type", new Dictionary <string, string> { { "data-key", "data-value" } }, "category", BreadcrumbLevel.Warning)); sut.SetExtra("extra_key", "extra_value"); sut.Fingerprint = new[] { "fingerprint" }; sut.SetTag("tag_key", "tag_value"); var actualString = sut.ToJsonString(); var actual = SentryEvent.FromJson(Json.Parse(actualString)); // Assert actual.Should().BeEquivalentTo(sut, o => { // Exceptions are not deserialized o.Excluding(x => x.Exception); // Timestamps lose some precision when writing to JSON o.Using <DateTimeOffset>(ctx => ctx.Subject.Should().BeCloseTo(ctx.Expectation, TimeSpan.FromMilliseconds(1)) ).WhenTypeIs <DateTimeOffset>(); return(o); }); }
private static async Task Main() { // When the SDK is disabled, no callback is executed: await SentrySdk.ConfigureScopeAsync(async scope => { // Never executed: // This could be any async I/O operation, like a DB query await Task.Yield(); scope.SetExtra("Key", "Value"); }); // Enable the SDK using (SentrySdk.Init(o => { // Send stack trace for events that were not created from an exception // e.g: CaptureMessage, log.LogDebug, log.LogInformation ... o.AttachStacktrace = true; // Sentry won't consider code from namespace LibraryX.* as part of the app code and will hide it from the stacktrace by default // To see the lines from non `AppCode`, select `Full`. Will include non App code like System.*, Microsoft.* and LibraryX.* o.AddInAppExclude("LibraryX."); // Before excluding all prefixed 'LibraryX.', any stack trace from a type namespaced 'LibraryX.Core' will be considered InApp. o.AddInAppInclude("LibraryX.Core"); // Send personal identifiable information like the username logged on to the computer and machine name o.SendDefaultPii = true; // To enable event sampling, uncomment: // o.SampleRate = 0.5f; // Randomly drop (don't send to Sentry) half of events // Modifications to event before it goes out. Could replace the event altogether o.BeforeSend = @event => { // Drop an event altogether: if (@event.Tags.ContainsKey("SomeTag")) { return(null); } return(@event); }; // Allows inspecting and modifying, returning a new or simply rejecting (returning null) o.BeforeBreadcrumb = crumb => { // Don't add breadcrumbs with message containing: if (crumb.Message?.Contains("bad breadcrumb") == true) { return(null); } return(crumb); }; // Ignore exception by its type: o.AddExceptionFilterForType <XsltCompileException>(); // Configure the background worker which sends events to sentry: // Wait up to 5 seconds before shutdown while there are events to send. o.ShutdownTimeout = TimeSpan.FromSeconds(5); // Enable SDK logging with Debug level o.Debug = true; // To change the verbosity, use: // o.DiagnosticLevel = SentryLevel.Info; // To use a custom logger: // o.DiagnosticLogger = ... // Using a proxy: o.HttpProxy = null; //new WebProxy("https://*****:*****@user{timestamp}.com"; SentrySdk.CaptureUserFeedback(new UserFeedback(eventId, user, email, "this is a sample user feedback")); var error = new Exception("Attempting to send this multiple times"); // Only the first capture will be sent to Sentry for (var i = 0; i < 3; i++) { // The SDK is able to detect duplicate events: // This is useful, for example, when multiple loggers log the same exception. Or exception is re-thrown and recaptured. SentrySdk.CaptureException(error); } var count = 10; for (var i = 0; i < count; i++) { const string msg = "{0} of {1} items we'll wait to flush to Sentry!"; SentrySdk.CaptureEvent(new SentryEvent { Message = new SentryMessage { Message = msg, Formatted = string.Format(msg, i, count) }, Level = SentryLevel.Debug }); } // Console output will show queue being flushed. Task completes then and timeout is never reached (you don't need to wait a day :) await SentrySdk.FlushAsync(TimeSpan.FromDays(1)); // ------------------------- // A custom made client, that could be registered with DI, // would get disposed by the container on app shutdown var evt = new SentryEvent(); evt.Message = "Starting new client"; evt.AddBreadcrumb("Breadcrumb directly to the event"); evt.User.Username = "******"; // Group all events with the following fingerprint: evt.SetFingerprint(new [] { "NewClientDebug" }); evt.Level = SentryLevel.Debug; SentrySdk.CaptureEvent(evt); // Using a different DSN: using (var adminClient = new SentryClient(new SentryOptions { Dsn = AdminDsn })) { // Make believe web framework middleware var middleware = new AdminPartMiddleware(adminClient, null); var request = new { Path = "/admin" }; // made up request middleware.Invoke(request); } // Dispose the client which flushes any queued events SentrySdk.CaptureException( new Exception("Error outside of the admin section: Goes to the default DSN")); } // On Dispose: SDK closed, events queued are flushed/sent to Sentry }
private static async Task Main(string[] args) { // When the SDK is disabled, no callback is executed: await SentrySdk.ConfigureScopeAsync(async scope => { // Never executed: // This could be any async I/O operation, like a DB query await Task.Yield(); scope.SetExtra("Key", "Value"); }); // Enable the SDK using (SentrySdk.Init(o => { // Send stack trace for events that were not created from an exception // e.g: CaptureMessage, log.LogDebug, log.LogInformation ... o.AttachStacktrace = true; // Sentry won't consider code from namespace LibraryX.* as part of the app code and will hide it from the stacktrace by default // To see the lines from non `AppCode`, select `Full`. That'll include non App code like System.*, Microsoft.* and LibraryX.* o.AddInAppExclude("LibraryX."); // Send personal identifiable information like the username logged on to the computer and machine name o.SendDefaultPii = true; // To enable event sampling, uncomment: // o.SampleRate = 0.5f; // Randomly drop (don't send to Sentry) half of events // Modifications to event before it goes out. Could replace the event altogether o.BeforeSend = @event => { // Drop an event altogether: if (@event.Tags.ContainsKey("SomeTag")) { return(null); } return(@event); }; // Allows inspecting and modifying, returning a new or simply rejecting (returning null) o.BeforeBreadcrumb = crumb => { // Don't add breadcrumbs with message containing: if (crumb.Message?.Contains("bad breadcrumb") == true) { return(null); } return(crumb); }; // Configure the background worker which sends events to sentry: // Wait up to 5 seconds before shutdown while there are events to send. o.ShutdownTimeout = TimeSpan.FromSeconds(5); // Enable SDK logging with Debug level o.Debug = true; // To change the verbosity, use: // o.DiagnosticsLevel = SentryLevel.Info; // To use a custom logger: // o.DiagnosticLogger = ... // Using a proxy: o.HttpProxy = null; //new WebProxy("https://localhost:3128"); // Example customizing the HttpClientHandlers created o.ConfigureHandler = (handler, dsn) => { handler.ServerCertificateCustomValidationCallback = // A custom certificate validation (sender, certificate, chain, sslPolicyErrors) => !certificate.Archived; }; // Access to the HttpClient created to serve the SentryClint o.ConfigureClient = (client, dsn) => { client.DefaultRequestHeaders.TryAddWithoutValidation("CustomHeader", new[] { "my value" }); }; })) { SentrySdk.AddBreadcrumb( "A 'bad breadcrumb' that will be rejected because of 'BeforeBreadcrumb callback above.'"); // Data added to the root scope (no PushScope called up to this point) // The modifications done here will affect all events sent and will propagate to child scopes. await SentrySdk.ConfigureScopeAsync(async scope => { scope.AddEventProcessor(new SomeEventProcessor()); scope.AddExceptionProcessor(new ArgumentExceptionProcessor()); // This could be any async I/O operation, like a DB query await Task.Yield(); scope.SetExtra("SomeExtraInfo", new { Data = "Value fetched asynchronously", ManaLevel = 199 }); }); SentrySdk.CaptureMessage("Some warning!", SentryLevel.Warning); var error = new Exception("Attempting to send this multiple times"); // Only the first capture will be sent to Sentry for (var i = 0; i < 3; i++) { // The SDK is able to detect duplicate events: // This is useful, for example, when multiple loggers log the same exception. Or exception is re-thrown and recaptured. SentrySdk.CaptureException(error); } // ------------------------- // A custom made client, that could be registered with DI, // would get disposed by the container on app shutdown var evt = new SentryEvent(); evt.Message = "Starting new client"; evt.AddBreadcrumb("Breadcrumb directly to the event"); evt.User.Username = "******"; // Group all events with the following fingerprint: evt.SetFingerprint(new [] { "NewClientDebug" }); evt.Level = SentryLevel.Debug; SentrySdk.CaptureEvent(evt); // Using a different DSN: var adminDsn = new Dsn(AdminDsn); using (var adminClient = new SentryClient(new SentryOptions { Dsn = adminDsn })) { // Make believe web framework middleware var middleware = new AdminPartMiddleware(adminClient, null); var request = new { Path = "/admin" }; // made up request middleware.Invoke(request); } // Dispose the client which flushes any queued events SentrySdk.CaptureException( new Exception("Error outside of the admin section: Goes to the default DSN")); } // On Dispose: SDK closed, events queued are flushed/sent to Sentry }
protected override void ProcessException( Exception exception, SentryEvent sentryEvent) { sentryEvent.AddBreadcrumb("Processor running on special exception."); }