Summary
TransactionNameProvider is only invoked when the transaction name is empty (i.e. routing failed entirely). When ASP.NET Core routing resolves a route template successfully, the provider is silently skipped — making it impossible to partially materialize route parameters in the transaction name without writing a custom middleware.
Current behavior
In SentryTracingMiddleware, the TransactionNameProvider delegate is guarded by:
if (transaction.Name == string.Empty)
{
transaction.Name = options.TransactionNameProvider?.Invoke(ctx) ?? ...;
}
Because routing resolves route templates like GET /api/v4/objects/{objectTypeName}/{objectId}/{operation}, transaction.Name is already populated before the provider is consulted. The delegate is never called.
Gap
There is no SDK-level hook that runs unconditionally after routing resolves and allows the transaction name to be rewritten. The full matrix of available hooks:
| Hook |
Status |
TransactionNameProvider |
Only fires when routing fails (name is empty) — unusable for routed requests |
SetBeforeSendTransaction |
transaction.Name is private set; NameSource has no setter — read-only |
ITransactionProcessor / AddTransactionProcessor |
Same constraint — name is not writable |
The practical workaround today is to inject a custom ASP.NET middleware that runs after routing and rewrites the transaction name via SentrySdk.GetSpan() or similar. This is undiscoverable and fragile.
A related issue (#3106) was closed with the same custom-middleware workaround.
Options
Option A — Unconditional TransactionNameProvider invocation
Remove (or make optional) the if (transaction.Name == string.Empty) guard. Let the provider run on every routed request. A null return falls back to the SDK default. This is the smallest possible change and preserves backward compatibility for users who don't configure a provider.
Option B — Expose a mutable ITransactionContext in SetBeforeSendTransaction
Add a writable Name and NameSource to the type passed into SetBeforeSendTransaction / transaction processors. This is a broader API surface change but gives maximum flexibility.
Option C — Add a dedicated TransactionProcessor hook with mutation support
Introduce a post-routing pipeline hook (e.g. OnTransactionNameResolved) that receives the resolved route data and can return a replacement name.
Recommendation
Option A is the lowest-risk path: make TransactionNameProvider fire unconditionally and treat a null return as "keep the SDK default." This directly fixes the documented (but broken) use case with no breaking API change.
Action taken on behalf of a Sentry support escalation.
Summary
TransactionNameProvideris only invoked when the transaction name is empty (i.e. routing failed entirely). When ASP.NET Core routing resolves a route template successfully, the provider is silently skipped — making it impossible to partially materialize route parameters in the transaction name without writing a custom middleware.Current behavior
In
SentryTracingMiddleware, theTransactionNameProviderdelegate is guarded by:Because routing resolves route templates like
GET /api/v4/objects/{objectTypeName}/{objectId}/{operation},transaction.Nameis already populated before the provider is consulted. The delegate is never called.Gap
There is no SDK-level hook that runs unconditionally after routing resolves and allows the transaction name to be rewritten. The full matrix of available hooks:
TransactionNameProviderSetBeforeSendTransactiontransaction.Nameisprivate set;NameSourcehas no setter — read-onlyITransactionProcessor/AddTransactionProcessorThe practical workaround today is to inject a custom ASP.NET middleware that runs after routing and rewrites the transaction name via
SentrySdk.GetSpan()or similar. This is undiscoverable and fragile.A related issue (#3106) was closed with the same custom-middleware workaround.
Options
Option A — Unconditional
TransactionNameProviderinvocationRemove (or make optional) the
if (transaction.Name == string.Empty)guard. Let the provider run on every routed request. A null return falls back to the SDK default. This is the smallest possible change and preserves backward compatibility for users who don't configure a provider.Option B — Expose a mutable
ITransactionContextinSetBeforeSendTransactionAdd a writable
NameandNameSourceto the type passed intoSetBeforeSendTransaction/ transaction processors. This is a broader API surface change but gives maximum flexibility.Option C — Add a dedicated
TransactionProcessorhook with mutation supportIntroduce a post-routing pipeline hook (e.g.
OnTransactionNameResolved) that receives the resolved route data and can return a replacement name.Recommendation
Option A is the lowest-risk path: make
TransactionNameProviderfire unconditionally and treat a null return as "keep the SDK default." This directly fixes the documented (but broken) use case with no breaking API change.Action taken on behalf of a Sentry support escalation.