Пример #1
0
        public void Implicit_ToGuid()
        {
            var  expected = new SentryId(Guid.NewGuid());
            Guid actual   = expected;

            Assert.Equal(expected.ToString(), actual.ToString("N"));
        }
Пример #2
0
 /// <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)
 {
 }
Пример #3
0
        public void Implicit_ToGuid()
        {
            var  expected = SentryId.Create();
            Guid actual   = expected;

            Assert.Equal(expected.ToString(), actual.ToString("N"));
        }
Пример #4
0
        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);
        }
Пример #5
0
        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);
        }
Пример #6
0
        public void ToString_Equal_GuidToStringN()
        {
            var      expected = Guid.NewGuid();
            SentryId actual   = expected;

            Assert.Equal(expected.ToString("N"), actual.ToString());
        }
Пример #7
0
        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
        }
Пример #8
0
    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);
    }
Пример #9
0
 /// <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)
 {
 }
Пример #10
0
        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();
        }
Пример #12
0
        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;
        }
Пример #13
0
 /// <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;
 }
Пример #14
0
        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));
        }
Пример #16
0
        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);
        }
Пример #18
0
 /// <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;
 }
Пример #19
0
        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}");
            }
        }
Пример #20
0
        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\"" +
                "}");
        }
Пример #21
0
    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);
    }
Пример #22
0
    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);
    }
Пример #23
0
 public UserFeedbackDialog(SentryId sentryId)
 {
     _sentryId = sentryId;
     InitializeComponent();
 }
Пример #24
0
        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);
            });
        }
Пример #25
0
        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
                                                                             ));
        }