Skip to content

Conversation

@jamescrosswell
Copy link
Collaborator

@jamescrosswell jamescrosswell commented Jun 25, 2025

These are just generally useful methods. We use them a lot internally (which is why we have HubExtensions for them) but they're not yet available on the SentrySdk class, which means it's sometimes difficult for customers to be able to use them.

A demonstration of why this is desirable is in #4304. Without these methods on the SentrySdk, either instrumenting that middleware is very verbose or customers have to know that SentrySdk and IHub have different functionality and they need to resolve an instance of IHub from the service provider and use this... either way, it's a lot more effort to do something pretty rudimentary.

@jamescrosswell jamescrosswell marked this pull request as ready for review June 25, 2025 07:21
Copy link
Member

@bruno-garcia bruno-garcia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though we're going away from transactions, lots of apps instrumented with transactinos already (I have a few) so this helps

@bruno-garcia
Copy link
Member

@sentry review

@bruno-garcia
Copy link
Member

@sentry review is more for testing the tool itself btw, this is gtg imo

@seer-by-sentry
Copy link

On it! We are reviewing the PR and will provide feedback shortly.

1 similar comment
@seer-by-sentry
Copy link

On it! We are reviewing the PR and will provide feedback shortly.

@seer-by-sentry
Copy link

PR Description

This pull request introduces StartSpan and GetTransaction methods to the SentrySdk class, providing a simplified and more discoverable way for users to create spans and access the currently active transaction. This aims to improve the ease of use for performance monitoring features within the Sentry .NET SDK.

Click to see more

Key Technical Changes

Two new public static methods, StartSpan(string operation, string description) and GetTransaction(), are added to SentrySdk.cs. StartSpan delegates to the StartSpan extension method on the IHub interface, which either creates a child span of the current transaction or starts a new transaction if none exists. GetTransaction delegates to the GetTransaction extension method on IHub, which retrieves the currently active transaction from the scope. API approval tests are updated to reflect the new public API surface.

Architecture Decisions

The decision to add these methods directly to SentrySdk provides a convenient and centralized access point. The implementation leverages the existing IHub and its extension methods to maintain consistency with the SDK's internal architecture. The StartSpan method's behavior of creating a new transaction if one doesn't exist is a notable architectural choice that simplifies usage but may require careful documentation to avoid unexpected behavior.

Dependencies and Interactions

These changes depend on the IHub interface and its extension methods, specifically StartSpan and GetTransaction. They interact with the scope management system to retrieve the current transaction. No new external dependencies are introduced.

Risk Considerations

The StartSpan method's dual behavior (creating a child span or a new transaction) could be a potential source of confusion if not clearly documented. Users might expect it to always create a span and be surprised when it creates a transaction. Thorough testing and clear documentation are crucial to mitigate this risk. Additionally, the performance impact of frequently calling GetTransaction should be considered, although the implementation is relatively lightweight.

Notable Implementation Details

The StartSpan method in HubExtensions starts a new transaction by calling hub.StartTransaction(operation, description) when no transaction is active. This means the operation is used as the transaction name and the description is used as the transaction description. This might not be intuitive for users expecting span semantics. The DebuggerStepThrough attribute is added to GetTransaction in SentrySdk.cs to improve the debugging experience.

@seer-by-sentry
Copy link

PR Description

This pull request introduces two new methods, StartSpan and GetTransaction, to the SentrySdk class. The primary goal is to provide a simplified and more discoverable way for users to create spans and access the currently active transaction without directly interacting with the IHub interface. This enhances the usability of the Sentry SDK for performance monitoring.

Click to see more

Key Technical Changes

The key technical changes involve adding the StartSpan(string operation, string description) method, which starts a span using the CurrentHub, and the GetTransaction() method, which retrieves the currently active transaction from the CurrentHub. These methods are implemented as static methods in SentrySdk and delegate directly to the corresponding methods in the IHub interface. API approval tests were updated to include these new methods in the public API surface.

Architecture Decisions

The architectural decision was to expose these methods directly through the SentrySdk facade, following the existing pattern of providing static access to the underlying IHub implementation. This avoids requiring users to obtain an instance of the IHub directly, simplifying the API and improving discoverability. The methods delegate to the CurrentHub to maintain the existing architecture and ensure consistency in how spans and transactions are managed.

Dependencies and Interactions

These changes depend on the IHub interface and its implementation (Hub). The StartSpan method interacts with the scope management within the Hub to create and activate the new span. The GetTransaction method interacts with the scope to retrieve the active transaction. There are no new external dependencies introduced by this pull request.

Risk Considerations

The primary risk is related to the potential for misuse of the StartSpan method if users are not aware of the existing transaction management within the Sentry SDK. It's important to ensure that the documentation clearly explains when to use StartSpan versus StartTransaction. Additionally, there's a risk of introducing performance regressions if the CurrentHub is accessed frequently. Unit tests should be added to ensure the new methods function as expected and do not introduce any unexpected side effects.

Notable Implementation Details

The implementation delegates directly to the CurrentHub to leverage existing span and transaction management logic. The DebuggerStepThrough attribute is used to improve the debugging experience. Parameter validation is missing for the StartSpan method, which could lead to issues if the operation name is null or empty. The XML documentation for the new methods could be improved to provide more context and clarity.

Comment on lines +640 to +641
/// </summary>
public static ISpan StartSpan(string operation, string description) => CurrentHub.StartSpan(operation, description);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding parameter validation for the StartSpan method. The operation and description parameters should be validated for null or empty values to provide better error messages and prevent potential issues downstream. Consider adding ArgumentNullException checks or at least XML documentation specifying the expected behavior with null parameters.

Suggested change
/// </summary>
public static ISpan StartSpan(string operation, string description) => CurrentHub.StartSpan(operation, description);
/// <summary>
/// Starts a transaction if there is not already one active on the scope, otherwise starts a new child span on the
/// currently active transaction.
/// </summary>
/// <param name="operation">The operation name. Cannot be null or empty.</param>
/// <param name="description">The span description. Cannot be null or empty.</param>
/// <exception cref="ArgumentNullException">Thrown when operation or description is null.</exception>
/// <exception cref="ArgumentException">Thrown when operation or description is empty.</exception>
public static ISpan StartSpan(string operation, string description)
{
if (string.IsNullOrEmpty(operation))
throw new ArgumentException("Operation cannot be null or empty", nameof(operation));
if (string.IsNullOrEmpty(description))
throw new ArgumentException("Description cannot be null or empty", nameof(description));
return CurrentHub.StartSpan(operation, description);
}

Comment on lines +637 to +641
/// <summary>
/// Starts a transaction if there is not already one active on the scope, otherwise starts a new child span on the
/// currently active transaction.
/// </summary>
public static ISpan StartSpan(string operation, string description) => CurrentHub.StartSpan(operation, description);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XML documentation for the StartSpan method should be more detailed. Consider adding information about the returned type and when this method would return null or a no-op span (when the SDK is disabled). Also, add <param> tags to document the parameters.

Suggested change
/// <summary>
/// Starts a transaction if there is not already one active on the scope, otherwise starts a new child span on the
/// currently active transaction.
/// </summary>
public static ISpan StartSpan(string operation, string description) => CurrentHub.StartSpan(operation, description);
/// <summary>
/// Starts a transaction if there is not already one active on the scope, otherwise starts a new child span on the
/// currently active transaction.
/// </summary>
/// <param name="operation">The operation name for the span.</param>
/// <param name="description">The description for the span.</param>
/// <returns>An <see cref="ISpan"/> representing the started span, or a no-op span if the SDK is disabled.</returns>

Comment on lines 700 to 705
/// <summary>
/// Gets the last active span.
/// Gets the currently active transaction
/// </summary>
[DebuggerStepThrough]
public static ITransactionTracer? GetTransaction() => CurrentHub.GetTransaction();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XML documentation comment has inconsistent formatting. The comment ends with a period for GetTransaction() but not for the other methods. Consider maintaining consistent documentation style throughout the class for better readability and professional appearance.

Suggested change
/// <summary>
/// Gets the last active span.
/// Gets the currently active transaction
/// </summary>
[DebuggerStepThrough]
public static ITransactionTracer? GetTransaction() => CurrentHub.GetTransaction();
/// <summary>
/// Gets the currently active transaction.
/// </summary>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

broke the indentation

Comment on lines 700 to 704
/// <summary>
/// Gets the last active span.
/// Gets the currently active transaction
/// </summary>
[DebuggerStepThrough]
public static ITransactionTracer? GetTransaction() => CurrentHub.GetTransaction();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XML documentation for GetTransaction has inconsistent formatting with a missing period at the end of the summary. For consistency with other methods in the class, it should end with a period.

Suggested change
/// <summary>
/// Gets the last active span.
/// Gets the currently active transaction
/// </summary>
[DebuggerStepThrough]
public static ITransactionTracer? GetTransaction() => CurrentHub.GetTransaction();
/// <summary>
/// Gets the currently active transaction.
/// </summary>

Comment on lines +706 to 708
/// <summary>
/// Gets the last active span
/// </summary>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XML documentation for GetSpan was updated but now has inconsistent formatting. The previous comment about "Gets the last active span" was more descriptive than "Gets the last active span" without proper context. Consider improving the documentation to clarify what "last active" means.

Suggested change
/// <summary>
/// Gets the last active span
/// </summary>
/// <summary>
/// Gets the currently active span, or null if no span is active.
/// </summary>

Comment on lines 700 to 705
/// <summary>
/// Gets the last active span.
/// Gets the currently active transaction
/// </summary>
[DebuggerStepThrough]
public static ITransactionTracer? GetTransaction() => CurrentHub.GetTransaction();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GetTransaction() method should include XML documentation for the return value to clarify when it returns null vs a valid transaction. This helps developers understand the expected behavior and handle null returns appropriately.

Suggested change
/// <summary>
/// Gets the last active span.
/// Gets the currently active transaction
/// </summary>
[DebuggerStepThrough]
public static ITransactionTracer? GetTransaction() => CurrentHub.GetTransaction();
/// <summary>
/// Gets the currently active transaction.
/// </summary>
/// <returns>The active transaction tracer if one exists, otherwise null.</returns>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

broken indentation

@jamescrosswell jamescrosswell merged commit bba8d4c into main Jun 25, 2025
14 of 15 checks passed
@jamescrosswell jamescrosswell deleted the sentrysdk-startspan branch June 25, 2025 20:55
@github-actions
Copy link
Contributor

Fails
🚫 Please consider adding a changelog entry for the next release.

Instructions and example for changelog

Please add an entry to CHANGELOG.md to the "Unreleased" section. Make sure the entry includes this PR's number.

Example:

## Unreleased

- Add StartSpan and GetTransaction methods to the SentrySdk ([#4303](https://github.com/getsentry/sentry-dotnet/pull/4303))

If none of the above apply, you can opt out of this check by adding #skip-changelog to the PR description.

Generated by 🚫 dangerJS against a98db40

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants