public async Task Transaction_binds_exception_thrown() { // Arrange TransactionSamplingContext samplingContext = null; var sentryClient = Substitute.For <ISentryClient>(); var hub = new Internal.Hub(new SentryOptions { Dsn = DsnSamples.ValidDsnWithoutSecret, TracesSampler = ctx => { samplingContext = ctx; return(1); } }, sentryClient); var exception = new Exception(); 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.Use(async(r, c) => { try { await c().ConfigureAwait(false); } catch { // We just want to know if it got into Sentry's Hub } }); app.UseSentryTracing(); app.UseEndpoints(routes => { routes.Map("/person/{id}", _ => throw exception); }); }) ); var client = server.CreateClient(); // Act await client.GetAsync("/person/13"); // Assert Assert.True(hub.ExceptionToSpanMap.TryGetValue(exception, out var span)); Assert.Equal(SpanStatus.InternalError, span.Status); }
public ITransaction StartTransaction( ITransactionContext context, IReadOnlyDictionary <string, object?> customSamplingContext) { var transaction = new Transaction(this, context); // Transactions are not handled by event processors, so some things need to be added manually // Apply scope ScopeManager.GetCurrent().Key.Apply(transaction); // SDK information var nameAndVersion = MainSentryEventProcessor.NameAndVersion; var protocolPackageName = MainSentryEventProcessor.ProtocolPackageName; if (transaction.Sdk.Version == null && transaction.Sdk.Name == null) { transaction.Sdk.Name = Constants.SdkName; transaction.Sdk.Version = nameAndVersion.Version; } if (nameAndVersion.Version != null) { transaction.Sdk.AddPackage(protocolPackageName, nameAndVersion.Version); } // Release information transaction.Release ??= _options.Release ?? ReleaseLocator.GetCurrent(); // Environment information var foundEnvironment = EnvironmentLocator.Locate(); transaction.Environment ??= (string.IsNullOrWhiteSpace(foundEnvironment) ? string.IsNullOrWhiteSpace(_options.Environment) ? Constants.ProductionEnvironmentSetting : _options.Environment : foundEnvironment); // Make a sampling decision if it hasn't been made already. // It could have been made by this point if the transaction was started // from a trace header which contains a sampling decision. if (transaction.IsSampled is null) { var samplingContext = new TransactionSamplingContext( context, customSamplingContext ); var sampleRate = // Custom sampler may not exist or may return null, in which case we fallback // to the static sample rate. _options.TracesSampler?.Invoke(samplingContext) ?? _options.TracesSampleRate; transaction.IsSampled = sampleRate switch {
public async Task Transaction_sampling_context_contains_HTTP_context_data() { // Arrange TransactionSamplingContext samplingContext = null; var sentryClient = Substitute.For <ISentryClient>(); var hub = new Internal.Hub(new SentryOptions { Dsn = DsnSamples.ValidDsnWithoutSecret, TracesSampler = ctx => { samplingContext = ctx; return(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 await client.GetAsync("/person/13"); // Assert samplingContext.Should().NotBeNull(); samplingContext.TryGetHttpMethod().Should().Be("GET"); samplingContext.TryGetHttpRoute().Should().Be("/person/{id}"); samplingContext.TryGetHttpPath().Should().Be("/person/13"); }
/// <summary> /// Gets the HTTP path associated with the transaction. /// May return null if the value has not been set by the integration. /// </summary> /// <remarks> /// This method extracts data from <see cref="TransactionSamplingContext.CustomSamplingContext"/> /// which is populated by Sentry's ASP.NET Core integration. /// </remarks> public static string?TryGetHttpPath(this TransactionSamplingContext samplingContext) => samplingContext.CustomSamplingContext.GetValueOrDefault(KeyForHttpPath) as string;