Skip to content

Conversation

@majanjua-amzn
Copy link

@majanjua-amzn majanjua-amzn commented Oct 16, 2025

Fixes: N/A
Design discussion issue: open-telemetry/opentelemetry-specification#4024

Changes

Changes based loosely on the same changes made to opentelemetry-java: open-telemetry/opentelemetry-java#6367

This change creates a new ExtendedBaseProcessor that allows users to implement onEnding functionality to their processor, as per the spec: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#onending

Specific changes:

  • Changed CompositeProcessor to be extended from the new ExtendedBaseProcessor to support processors that have OnEnding
  • Created new ExtendedBaseProcessor as the place where this functionality is added, so as to not break any current experience of extending the normal BaseProcessor
  • Updated TestActivityProcessor to extend the new OnEnding method while being agnostic to it for tests that don't need it
  • Updated unit tests to verify the running order of the span lifecycle is correct and includes the OnEnding invocation

Merge requirement checklist

  • CONTRIBUTING guidelines followed (license requirements, nullable enabled, static analysis, etc.)
  • Unit tests added/updated
  • Appropriate CHANGELOG.md files updated for non-trivial changes
  • Changes in public API reviewed (if applicable)

@majanjua-amzn majanjua-amzn requested a review from a team as a code owner October 16, 2025 22:42
@github-actions github-actions bot added the pkg:OpenTelemetry Issues related to OpenTelemetry NuGet package label Oct 16, 2025
@majanjua-amzn majanjua-amzn force-pushed the main branch 4 times, most recently from 85231aa to e108c44 Compare October 20, 2025 20:46
@codecov
Copy link

codecov bot commented Oct 21, 2025

Codecov Report

❌ Patch coverage is 94.44444% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 86.76%. Comparing base (94b98e2) to head (92fa740).
⚠️ Report is 6 commits behind head on main.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/OpenTelemetry/ExtendedBaseProcessor.cs 0.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #6617      +/-   ##
==========================================
+ Coverage   86.73%   86.76%   +0.02%     
==========================================
  Files         258      259       +1     
  Lines       11958    11976      +18     
==========================================
+ Hits        10372    10391      +19     
+ Misses       1586     1585       -1     
Flag Coverage Δ
unittests-Project-Experimental 86.75% <94.44%> (+0.08%) ⬆️
unittests-Solution 86.44% <94.44%> (-0.23%) ⬇️
unittests-UnstableCoreLibraries-Experimental 86.07% <ø> (-0.37%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/OpenTelemetry/CompositeProcessor.cs 95.83% <100.00%> (+0.24%) ⬆️
src/OpenTelemetry/Trace/TracerProviderSdk.cs 99.38% <100.00%> (+0.02%) ⬆️
src/OpenTelemetry/ExtendedBaseProcessor.cs 0.00% <0.00%> (ø)

... and 3 files with indirect coverage changes

@Kielek
Copy link
Member

Kielek commented Oct 21, 2025

This feature is still in development phase. It means that we cannot include it into stable releases for this package.
We have possibility to make it happen for unstable versions.

You can make full search for OTEL1000 in this repository. In this way you can find an example how to implement conditional compilation + required documentation.
OTEL1005 is the first available code at the moment.

Another thing for consideration: double check if it is not breaking change on binary level when you are introducing new class to the inheritance.

@github-actions github-actions bot added infra Infra work - CI/CD, code coverage, linters documentation Documentation related labels Oct 23, 2025
@majanjua-amzn majanjua-amzn force-pushed the main branch 2 times, most recently from f176ccd to e1a2717 Compare October 24, 2025 16:38
@majanjua-amzn
Copy link
Author

I think I've appropriately added the OTEL1005 label where needed, could I get some help rerunning the workflows to see if there are any other remaining issues?

And regarding the following, is there a way to do so besides just running the build/tests? Thanks in advance

Another thing for consideration: double check if it is not breaking change on binary level when you are introducing new class to the inheritance.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 1, 2025

This PR was marked stale due to lack of activity and will be closed in 7 days. Commenting or pushing will instruct the bot to automatically remove the label. This bot runs once per day.

@github-actions github-actions bot added the Stale Issues and pull requests which have been flagged for closing due to inactivity label Nov 1, 2025
@Kielek Kielek added keep-open Prevents issues and pull requests being closed as stale and removed Stale Issues and pull requests which have been flagged for closing due to inactivity labels Nov 4, 2025
This change creates a new ExtendedBaseProcessor that allows users
to implement onEnding functionality to their processor, as per
the spec: https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/sdk.md#onending
@majanjua-amzn
Copy link
Author

Could I get some help with running the workflows and receiving a review? Thanks

Comment on lines +15 to +17
#pragma warning disable CA1012 // Abstract types should not have public constructors
public abstract class ExtendedBaseProcessor<T> : BaseProcessor<T>
#pragma warning restore CA1012 // Abstract types should not have public constructors
Copy link
Member

Choose a reason for hiding this comment

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

This should be fixed by adding an explicit protected constructor.


## Overview

This is an experimental API for modifying spans before they end/close
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
This is an experimental API for modifying spans before they end/close
This is an experimental API for modifying spans before they end/close.

#### ExtendedBaseProcessor

The abstract class `ExtendedBaseProcessor` provides an extension of the
`BaseProcessor` that allows spans to be modified before they end as per the
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
`BaseProcessor` that allows spans to be modified before they end as per the
`BaseProcessor` class that allows spans to be modified before they end as per the


The abstract class `ExtendedBaseProcessor` provides an extension of the
`BaseProcessor` that allows spans to be modified before they end as per the
OpenTelemetry specification. It provides the `OnEnding` function that is called
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
OpenTelemetry specification. It provides the `OnEnding` function that is called
OpenTelemetry specification. It provides the `OnEnding` method that is called

`BaseProcessor` that allows spans to be modified before they end as per the
OpenTelemetry specification. It provides the `OnEnding` function that is called
during the span `End()` operation. The end timestamp MUST have been computed
(the `OnEnding` method duration is not included in the span duration). The Span
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
(the `OnEnding` method duration is not included in the span duration). The Span
(the `OnEnding` method duration is not included in the span duration). The `Span`

/// </summary>
/// <typeparam name="T">The type of object to be processed.</typeparam>
#if EXPOSE_EXPERIMENTAL_FEATURES
public class CompositeProcessor<T> : ExtendedBaseProcessor<T>
Copy link
Member

Choose a reason for hiding this comment

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

Checked the documentation and it should be OK to change the base class without making a breaking change as all the members in the new class aren't abstract.

Comment on lines +84 to +90
for (var cur = this.Head; cur != null; cur = cur.Next)
{
if (typeof(ExtendedBaseProcessor<T>).IsAssignableFrom(cur.Value.GetType()))
{
((ExtendedBaseProcessor<T>)cur.Value).OnEnding(data);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Would this work to avoid reflection and casting?

Suggested change
for (var cur = this.Head; cur != null; cur = cur.Next)
{
if (typeof(ExtendedBaseProcessor<T>).IsAssignableFrom(cur.Value.GetType()))
{
((ExtendedBaseProcessor<T>)cur.Value).OnEnding(data);
}
}
for (var current = this.Head; current != null; cur = current.Next)
{
if (current.Value is ExtendedBaseProcessor<T> processor)
{
processor.OnEnding(data);
}
}

/// The started telemetry object.
/// </param>
/// <remarks>
/// This function is called synchronously on the thread which ended
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/// This function is called synchronously on the thread which ended
/// This method is called synchronously on the thread which ended

Comment on lines +193 to +196
if (typeof(ExtendedBaseProcessor<Activity>).IsAssignableFrom(this.processor?.GetType()))
{
(this.processor as ExtendedBaseProcessor<Activity>)?.OnEnding(activity);
}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (typeof(ExtendedBaseProcessor<Activity>).IsAssignableFrom(this.processor?.GetType()))
{
(this.processor as ExtendedBaseProcessor<Activity>)?.OnEnding(activity);
}
if (this.processor is ExtendedBaseProcessor<Activity> extended)
{
extended.OnEnding(activity);
}

Comment on lines +234 to +237
if (typeof(ExtendedBaseProcessor<Activity>).IsAssignableFrom(this.processor?.GetType()))
{
(this.processor as ExtendedBaseProcessor<Activity>)?.OnEnding(activity);
}
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
if (typeof(ExtendedBaseProcessor<Activity>).IsAssignableFrom(this.processor?.GetType()))
{
(this.processor as ExtendedBaseProcessor<Activity>)?.OnEnding(activity);
}
if (this.processor is ExtendedBaseProcessor<Activity> extended)
{
extended.OnEnding(activity);
}

@martincostello martincostello changed the title feat: add on ending span processor functionality [OpenTelemetry] Add OnEnding span processor functionality Nov 14, 2025
* Add support for .NET 10.0.
([#6307](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6307))

* feat: add on ending span processor functionality
Copy link
Member

Choose a reason for hiding this comment

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

https://github.com/open-telemetry/opentelemetry-dotnet/tree/main/docs/trace/extending-the-sdk#processor

Please improve this document to talk about when users should implement OnEnd vs the new option.
I am not sure of the answer given .NET's use of Activity to represent span. This must be clear to avoid user confusion once this is released.

Copy link
Member

@cijothomas cijothomas left a comment

Choose a reason for hiding this comment

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

Requesting changes to make sure this is actually needed. While the Spec newly added OnEnding to allow Span modification, OTel .NET uses Activity to represent span, which has slightly different semantics than the spec. And Activity is already writeable in OnEnd.

Do we need this in OTel .NET at all? If yes, please list the reason(s) before adding this.

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

Labels

documentation Documentation related infra Infra work - CI/CD, code coverage, linters keep-open Prevents issues and pull requests being closed as stale pkg:OpenTelemetry Issues related to OpenTelemetry NuGet package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants