public void Implicit_ToGuid() { var expected = new SentryId(Guid.NewGuid()); Guid actual = expected; Assert.Equal(expected.ToString(), actual.ToString("N")); }
/// <summary> /// Initializes an instance of <see cref="TransactionContext"/>. /// </summary> public TransactionContext( string name, string operation, bool?isSampled) : this(SpanId.Create(), null, SentryId.Create(), name, operation, "", null, isSampled, null) { }
public void Implicit_ToGuid() { var expected = SentryId.Create(); Guid actual = expected; Assert.Equal(expected.ToString(), actual.ToString("N")); }
public async Task Roundtrip_WithUserFeedback_Success() { // Arrange var feedback = new UserFeedback( SentryId.Create(), "Donald J. Trump", "*****@*****.**", "Everything sucks" ); using var envelope = Envelope.FromUserFeedback(feedback); using var stream = new MemoryStream(); // Act await envelope.SerializeAsync(stream); stream.Seek(0, SeekOrigin.Begin); using var envelopeRoundtrip = await Envelope.DeserializeAsync(stream); // Assert // Can't compare the entire object graph because output envelope contains evaluated length, // which original envelope doesn't have. envelopeRoundtrip.Header.Should().BeEquivalentTo(envelope.Header); envelopeRoundtrip.Items.Should().ContainSingle(); var payloadContent = (envelopeRoundtrip.Items[0].Payload as JsonSerializable)?.Source; payloadContent.Should().BeEquivalentTo(feedback); }
public async Task Roundtrip_WithUserFeedback_Success() { // Arrange var feedback = new UserFeedback( SentryId.Create(), "Someone Nice", "*****@*****.**", "Everything is great!"); using var envelope = Envelope.FromUserFeedback(feedback); #if !NET461 && !NETCOREAPP2_1 await #endif using var stream = new MemoryStream(); // Act await envelope.SerializeAsync(stream); stream.Seek(0, SeekOrigin.Begin); using var envelopeRoundtrip = await Envelope.DeserializeAsync(stream); // Assert // Can't compare the entire object graph because output envelope contains evaluated length, // which original envelope doesn't have. envelopeRoundtrip.Header.Should().BeEquivalentTo(envelope.Header); envelopeRoundtrip.Items.Should().ContainSingle(); envelopeRoundtrip.Items[0].Payload.Should().BeOfType <JsonSerializable>() .Which.Source.Should().BeEquivalentTo(feedback); }
public void ToString_Equal_GuidToStringN() { var expected = Guid.NewGuid(); SentryId actual = expected; Assert.Equal(expected.ToString("N"), actual.ToString()); }
public static string SendException(Exception exception) { #if !DEBUG string pluginDiretoryKey = nameof(Plugin.PluginPair.Metadata.PluginDirectory); if (exception.Data.Contains(pluginDiretoryKey)) { string pluginDirectory = exception.Data[pluginDiretoryKey] as string; bool debug = pluginDirectory.Contains(@"\Output\Release") || pluginDirectory.Contains(@"\Output\Release"); bool thirdParty = !pluginDirectory.Contains(Constant.ProgramDirectory); if (debug || thirdParty) { return(SentryId.Empty.ToString()); } } SentryId id = SentryId.Empty; SentrySdk.WithScope(scope => { scope.Level = SentryLevel.Fatal; id = SentrySdk.CaptureException(exception); }); return(id.ToString()); #else return(SentryId.Empty.ToString()); #endif }
public void SerializeObject_AllPropertiesSetToNonDefault_SerializesValidObject() { // Arrange var trace = new Trace { Operation = "op123", Status = SpanStatus.Aborted, IsSampled = false, ParentSpanId = SpanId.Parse("1000000000000000"), SpanId = SpanId.Parse("2000000000000000"), TraceId = SentryId.Parse("75302ac48a024bde9a3b3734a82e36c8") }; // Act var actual = trace.ToJsonString(); // Assert Assert.Equal( "{" + "\"type\":\"trace\"," + "\"span_id\":\"2000000000000000\"," + "\"parent_span_id\":\"1000000000000000\"," + "\"trace_id\":\"75302ac48a024bde9a3b3734a82e36c8\"," + "\"op\":\"op123\"," + "\"status\":\"aborted\"" + "}", actual); }
/// <summary> /// Initializes an instance of <see cref="TransactionContext"/>. /// </summary> public TransactionContext( SpanId?parentSpanId, SentryId traceId, string name, string operation, bool?isParentSampled) : this(SpanId.Create(), parentSpanId, traceId, name, operation, "", null, isParentSampled, isParentSampled) { }
public IHub GetSut() { Id = SentryId.Create(); var hub = Substitute.For <IHub>(); hub.IsEnabled.Returns(true); hub.CaptureEvent(Arg.Any <SentryEvent>()).Returns(Id); return(hub); }
public async Task Transaction_is_started_automatically_from_incoming_trace_header() { // Arrange ITransactionData transaction = null; var sentryClient = Substitute.For <ISentryClient>(); var hub = new Internal.Hub(sentryClient, new SentryOptions { Dsn = DsnSamples.ValidDsnWithoutSecret, TracesSampleRate = 1 }); var server = new TestServer(new WebHostBuilder() .UseDefaultServiceProvider(di => di.EnableValidation()) .UseSentry() .ConfigureServices(services => { services.AddRouting(); services.RemoveAll(typeof(Func <IHub>)); services.AddSingleton <Func <IHub> >(() => hub); }) .Configure(app => { app.UseRouting(); app.UseSentryTracing(); app.UseEndpoints(routes => { routes.Map("/person/{id}", _ => { transaction = hub.GetSpan() as ITransactionData; return(Task.CompletedTask); }); }); }) ); var client = server.CreateClient(); // Act using var request = new HttpRequestMessage(HttpMethod.Get, "/person/13") { Headers = { { "sentry-trace", "75302ac48a024bde9a3b3734a82e36c8-1000000000000000-0" } } }; await client.SendAsync(request); // Assert transaction.Should().NotBeNull(); transaction?.Name.Should().Be("GET /person/{id}"); transaction.TraceId.Should().Be(SentryId.Parse("75302ac48a024bde9a3b3734a82e36c8")); transaction.ParentSpanId.Should().Be(SpanId.Parse("1000000000000000")); transaction.IsSampled.Should().BeFalse(); }
void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) { SentryId sentryId = SentrySdk.CaptureException(e.Exception); e.Handled = true; crashReporter = new CrashReporter(e.Exception); crashReporter.Owner = Current.MainWindow; crashReporter.CurrentSentryId = sentryId; crashReporter.ShowDialog(); crashReporter = null; }
/// <summary> /// Initializes an instance of <see cref="TransactionContext"/>. /// </summary> public TransactionContext( SpanId spanId, SpanId?parentSpanId, SentryId traceId, string name, string operation, string description, SpanStatus?status, bool?isSampled) : base(spanId, parentSpanId, traceId, operation, description, status, isSampled) { Name = name; }
public void Parse_WithoutSampled_Works() { // Arrange const string headerValue = "75302ac48a024bde9a3b3734a82e36c8-1000000000000000"; // Act var header = SentryTraceHeader.Parse(headerValue); // Assert header.TraceId.Should().Be(SentryId.Parse("75302ac48a024bde9a3b3734a82e36c8")); header.SpanId.Should().Be(SpanId.Parse("1000000000000000")); header.IsSampled.Should().BeNull(); }
public static string GetShortId(this SentryId id) { if (id.Equals(SentryId.Empty)) { return(null); } string encoded = Convert.ToBase64String(((Guid)id).ToByteArray()); encoded = encoded .Replace("/", "_") .Replace("+", "-"); return(encoded.Substring(0, 16)); }
public void Serialization_Session_Success() { // Arrange var session = new Session( SentryId.Parse("75302ac48a024bde9a3b3734a82e36c8"), "bar", DateTimeOffset.Parse("2020-01-01T00:00:00+00:00", CultureInfo.InvariantCulture), "release123", "env123", "192.168.0.1", "Google Chrome" ); session.ReportError(); session.ReportError(); session.ReportError(); var sessionUpdate = new SessionUpdate( session, true, DateTimeOffset.Parse("2020-01-02T00:00:00+00:00", CultureInfo.InvariantCulture), 5, SessionEndStatus.Crashed ); // Act var json = sessionUpdate.ToJsonString(); // Assert json.Should().Be( "{" + "\"sid\":\"75302ac48a024bde9a3b3734a82e36c8\"," + "\"did\":\"bar\"," + "\"init\":true," + "\"started\":\"2020-01-01T00:00:00+00:00\"," + "\"timestamp\":\"2020-01-02T00:00:00+00:00\"," + "\"seq\":5," + "\"duration\":86400," + "\"errors\":3," + "\"status\":\"crashed\"," + "\"attrs\":{" + "\"release\":\"release123\"," + "\"environment\":\"env123\"," + "\"ip_address\":\"192.168.0.1\"," + "\"user_agent\":\"Google Chrome\"" + "}" + "}" ); }
public void Serialization_SentryUserFeedbacks_Success() { // Arrange var eventId = new SentryId(Guid.Parse("acbe351c61494e7b807fd7e82a435ffc")); var userFeedback = new UserFeedback(eventId, "*****@*****.**", "my comment", "myName"); using var stream = new MemoryStream(); // Act var serializedContent = Json.Serialize(userFeedback); // Assert var assertExpected = "{\"event_id\":\"acbe351c61494e7b807fd7e82a435ffc\",\"name\":\"myName\",\"email\":\"[email protected]\",\"comments\":\"my comment\"}"; Assert.Equal(assertExpected, serializedContent); }
/// <summary> /// Initializes an instance of <see cref="SpanContext"/>. /// </summary> public SpanContext( SpanId spanId, SpanId?parentSpanId, SentryId traceId, string operation, string?description, SpanStatus?status, bool?isSampled) { SpanId = spanId; ParentSpanId = parentSpanId; TraceId = traceId; Operation = operation; Description = description; Status = status; IsSampled = isSampled; }
private static void HandleException(Exception exception) { if (exception == null) { return; } SentryId eventId = default; SentrySdk.WithScope(scope => { scope.AddAttachment(AppConfigs.Configuration.FileLocation); eventId = SentrySdk.CaptureException(exception); } ); var exceptionMessage = exception.Message; if (exception.InnerException != null) { exceptionMessage += $"\n{exception.InnerException.Message}"; } var message = $@"It seems {Application.ProductName} has crashed. {exceptionMessage} Would you like to share more information with the developers?"; var result = MessageBox.Show(message, $@"{Application.ProductName} crashed...", MessageBoxButtons.YesNo, MessageBoxIcon.Error); if (result != DialogResult.Yes) { return; } using (new HourGlass()) { BrowserUtil.OpenUrl($"https://soundswitch.aaflalo.me/#sentry?eventId={eventId}"); } }
public void Serialization_SentryUserFeedbacks_Success() { // Arrange var eventId = new SentryId(Guid.Parse("acbe351c61494e7b807fd7e82a435ffc")); var userFeedback = new UserFeedback(eventId, "myName", "*****@*****.**", "my comment"); using var stream = new MemoryStream(); // Act var serializedContent = userFeedback.ToJsonString(); // Assert serializedContent.Should().Be( "{" + "\"event_id\":\"acbe351c61494e7b807fd7e82a435ffc\"," + "\"name\":\"myName\"," + "\"email\":\"[email protected]\"," + "\"comments\":\"my comment\"" + "}"); }
public void CreateUpdate_IncrementsSequenceNumber() { // Arrange var session = new Session( SentryId.Parse("75302ac48a024bde9a3b3734a82e36c8"), "bar", DateTimeOffset.Parse("2020-01-01T00:00:00+00:00", CultureInfo.InvariantCulture), "release123", "env123", "192.168.0.1", "Google Chrome"); // Act var sessionUpdate1 = session.CreateUpdate(true, DateTimeOffset.Now); var sessionUpdate2 = session.CreateUpdate(false, DateTimeOffset.Now); var sessionUpdate3 = session.CreateUpdate(false, DateTimeOffset.Now); // Assert sessionUpdate1.SequenceNumber.Should().Be(0); sessionUpdate2.SequenceNumber.Should().Be(1); sessionUpdate3.SequenceNumber.Should().Be(2); }
public void Clone_CopyValues() { // Arrange var trace = new Trace { Operation = "op123", Status = SpanStatus.Aborted, IsSampled = false, ParentSpanId = SpanId.Parse("1000000000000000"), SpanId = SpanId.Parse("2000000000000000"), TraceId = SentryId.Parse("75302ac48a024bde9a3b3734a82e36c8") }; // Act var clone = trace.Clone(); // Assert Assert.Equal(trace.Operation, clone.Operation); Assert.Equal(trace.Status, clone.Status); Assert.Equal(trace.IsSampled, clone.IsSampled); Assert.Equal(trace.ParentSpanId, clone.ParentSpanId); Assert.Equal(trace.SpanId, clone.SpanId); Assert.Equal(trace.TraceId, clone.TraceId); }
public UserFeedbackDialog(SentryId sentryId) { _sentryId = sentryId; InitializeComponent(); }
public void SerializeObject_AllPropertiesSetToNonDefault_SerializesValidObject() { // Arrange var timestamp = DateTimeOffset.MaxValue; var context = new TransactionContext( SpanId.Create(), SpanId.Create(), SentryId.Create(), "name123", "op123", "desc", SpanStatus.AlreadyExists, null, // sampling isn't serialized and getting FluentAssertions // to ignore that on Spans and contexts isn't really straight forward true); var transaction = new TransactionTracer(DisabledHub.Instance, context) { Description = "desc123", Status = SpanStatus.Aborted, User = new User { Id = "user-id" }, Request = new Request { Method = "POST" }, Sdk = new SdkVersion { Name = "SDK-test", Version = "1.1.1" }, Environment = "environment", Level = SentryLevel.Fatal, 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\"" } }, }; // Don't overwrite the contexts object as it contains trace data. // See https://github.com/getsentry/sentry-dotnet/issues/752 transaction.Sdk.AddPackage(new Package("name", "version")); transaction.AddBreadcrumb(new Breadcrumb(timestamp, "crumb")); transaction.AddBreadcrumb(new Breadcrumb( timestamp, "message", "type", new Dictionary <string, string> { { "data-key", "data-value" } }, "category", BreadcrumbLevel.Warning) ); transaction.SetExtra("extra_key", "extra_value"); transaction.Fingerprint = new[] { "fingerprint" }; transaction.SetTag("tag_key", "tag_value"); var child1 = transaction.StartChild("child_op123", "child_desc123"); child1.Status = SpanStatus.Unimplemented; child1.SetTag("q", "v"); child1.SetExtra("f", "p"); child1.Finish(SpanStatus.Unimplemented); var child2 = transaction.StartChild("child_op999", "child_desc999"); child2.Status = SpanStatus.OutOfRange; child2.SetTag("xxx", "zzz"); child2.SetExtra("f222", "p111"); child2.Finish(SpanStatus.OutOfRange); transaction.Finish(SpanStatus.Aborted); // Act var finalTransaction = new Transaction(transaction); var actualString = finalTransaction.ToJsonString(); var actual = Transaction.FromJson(Json.Parse(actualString)); // Assert actual.Should().BeEquivalentTo(finalTransaction, o => { // 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); }); }
public async Task Transaction_is_started_automatically_from_incoming_trace_header() { // Arrange var sentryClient = Substitute.For <ISentryClient>(); var hub = new Internal.Hub(new SentryOptions { Dsn = DsnSamples.ValidDsnWithoutSecret, TracesSampleRate = 1 }, sentryClient); var server = new TestServer(new WebHostBuilder() .UseDefaultServiceProvider(di => di.EnableValidation()) .UseSentry() .ConfigureServices(services => { services.AddRouting(); services.RemoveAll(typeof(Func <IHub>)); services.AddSingleton <Func <IHub> >(() => hub); }) .Configure(app => { app.UseRouting(); app.UseSentryTracing(); app.UseEndpoints(routes => { routes.Map("/person/{id}", _ => Task.CompletedTask); }); }) ); var client = server.CreateClient(); // Act using var request = new HttpRequestMessage(HttpMethod.Get, "/person/13") { Headers = { { "sentry-trace", "75302ac48a024bde9a3b3734a82e36c8-1000000000000000-0" } } }; await client.SendAsync(request); // Assert sentryClient.Received(1).CaptureTransaction(Arg.Is <Transaction>(t => t.Name == "GET /person/{id}" && t.TraceId == SentryId.Parse("75302ac48a024bde9a3b3734a82e36c8") && t.ParentSpanId == SpanId.Parse("1000000000000000") && t.IsSampled == false )); }