Skip to content

Activity should have AddExceptionMethod #53641

@DR9885

Description

@DR9885

Edited by @tarekgh

Proposal

This proposal aims to enable the recording of exceptions during tracing operations, in accordance with the OpenTelemetry Record Exception specification

namespace System.Diagnostics;

public class Activity
{
    public void RecordException(Exception exception, TagList tags = default, DateTimeOffset timestamp = default);
}

public delegate void ExceptionRecording(Activity activity, Exception exception, ref TagList tags);

public sealed class ActivityListener : IDisposable
{
    // Will be invoked when Activity.RecordException is called.
    public ExceptionRecording? ExceptionRecording { get; set; }
}

Notes

  • RecordException will save details of the exception into an ActivityEvent entry, adhering to the guidelines of the OpenTelemetry semantic convention.
  • RecordException captures information such as the stack trace, exception type name, and exception message, but not the exception object itself. This approach is chosen because the exception might be rethrown, potentially altering the stack trace. Additionally, exception objects can be large and complex, leading to performance issues.
  • Anyone interested in accessing the actual exception object during recording can use ActivityListener.ExceptionRecording, which provides a notification that includes the exception objects along with the tags to be recorded. When listeners are enabled, the behavior of RecordException will be as follows:
    • RecordException will iterate through all non-nullable ExceptionRecording listeners one by one, passing the exception object and the input tags list provided to RecordException. Listeners can add or modify tags as necessary.
    • If multiple registered listeners modify the same tags, the changes made by the last listener will prevail and be recorded in the event.
    • After calling all listeners, RecordException adds the populated event to the Activity.Events list. If any tags specified in the OpenTelemetry semantic convention are missing, they will be added to the tag list before the event is stored.
  • RecordException will always log the event, and there will be no option to suppress its addition.

The recorded event will have the name as exception and will include the following tags:


Usage Example

    using ActivitySource aSource =  new ActivitySource("SourceActivityListener");
    
    using ActivityListener listener = new ActivityListener();
    listener.ShouldListenTo = (activitySource) => object.ReferenceEquals(aSource, activitySource);
    listener.Sample = (ref ActivityCreationOptions<ActivityContext> activityOptions) => ActivitySamplingResult.AllData;
    listener.ExceptionRecording = (activity, exception, ref tags) => { /* access the exception and the tags */  };
    ActivitySource.AddActivityListener(listener);

    using Activity activity = aSource.StartActivity("AllDataRequestedActivity");
    activity.RecordException(new Exception("Exception to be recorded"), new TagList { { "exception.escaped", "true" } }, DateTimeOffset.UtcNow );
    
    ActivityEvent exceptionEvent = activity.Events.First();

Original Proposal

Activity should have AddExceptionMethod, rather than having to set these tags everytime.

        public static Activity AddException(this Activity activity, Exception ex)
        {
            return activity?.AddTag("event", "error")
                .AddTag("error", "true")
                .AddTag("error.kind", ex.GetType().Name)
                .AddTag("error.message", ex.Message)
                .AddTag("error.stack", ex.StackTrace);
        }

This should also have constants for these strings, for performance.

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-approvedAPI was approved in API review, it can be implementedarea-System.Diagnostics.ActivityblockingMarks issues that we want to fast track in order to unblock other important workfeature-requestin-prThere is an active PR which will close this issue when it is merged

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions