Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add RecordException overload accepting additional tags #3433

Merged
merged 17 commits into from
Jul 19, 2022

Conversation

alanwest
Copy link
Member

@alanwest alanwest commented Jul 7, 2022

Fixes #3369.

Adds RecordException overload accepting additional tags to add to the exception event.

public static void RecordException(this Activity activity, Exception ex, TagList tags)

@alanwest alanwest requested a review from a team as a code owner July 7, 2022 22:53
@codecov
Copy link

codecov bot commented Jul 7, 2022

Codecov Report

Merging #3433 (80e6ef2) into main (ab10e11) will increase coverage by 0.18%.
The diff coverage is 100.00%.

❗ Current head 80e6ef2 differs from pull request most recent head 6c50cf6. Consider uploading reports for the commit 6c50cf6 to get more accurate results

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #3433      +/-   ##
==========================================
+ Coverage   86.21%   86.39%   +0.18%     
==========================================
  Files         265      265              
  Lines        9598     9602       +4     
==========================================
+ Hits         8275     8296      +21     
+ Misses       1323     1306      -17     
Impacted Files Coverage Δ
src/OpenTelemetry.Api/Trace/ActivityExtensions.cs 95.23% <100.00%> (+1.12%) ⬆️
...ter.ZPages/Implementation/ZPagesActivityTracker.cs 97.14% <0.00%> (-2.86%) ⬇️
...Telemetry/Internal/SelfDiagnosticsEventListener.cs 97.65% <0.00%> (+0.78%) ⬆️
...metryProtocol/Implementation/ActivityExtensions.cs 94.50% <0.00%> (+3.29%) ⬆️
...emetry.Api/Internal/OpenTelemetryApiEventSource.cs 82.35% <0.00%> (+8.82%) ⬆️
...xporter.OpenTelemetryProtocol/OtlpTraceExporter.cs 77.27% <0.00%> (+18.18%) ⬆️
...entation/ExportClient/OtlpGrpcTraceExportClient.cs 78.57% <0.00%> (+28.57%) ⬆️

@CodeBlanch
Copy link
Member

@alanwest Could we use TagList?

Reasons...

  • Allocation free up to 8 tags.

  • Allocation free foreach.

  • Slightly nicer syntax (debatable 🤣) you can new it up using collection initializer like...

    activity.RecordException(ex, new() { new("myTag", "myValue") })

If you do decide to go with TagList it could be large so we should probably use in modifier:

 public static void RecordException(this Activity activity, Exception ex, in TagList tags)

@alanwest
Copy link
Member Author

alanwest commented Jul 11, 2022

Could we use TagList?

I agree with the benefits, but I guess the reason I didn't reach for TagList is that it is not used by any of the existing Activity APIs (might fact check me on this...). I was inclined to consider ActivityTagsCollection since that is what the ActivityEvent constructor takes and RecordException is effectively a specialized form of adding an event... but by and large most Activity APIs that take a list of tags accept IEnumerable<KeyValuePair<string, object>>, so I was trying not to make this API a unicorn 🦄.

Also, one might argue that RecordException should be offered by .NET itself since it is part of the spec and not as an extension method offered by us. So, in this sense I was trying to get into the heads of the .NET team and ask my self WWDND (what would .NET do)?

TagList implements IEnumerable<KeyValuePair<string, object>>, so it could still be used - albeit not with the sugary syntax. Could RecordException do a tags is TagList enumerateMeForFree to get the perf benefit? I guess there's probably a boxing in passing it to RecordException, but then would there still be a benefit when enumerating?

@cijothomas
Copy link
Member

Also, one might argue that RecordException should be offered by .NET itself since it is part of the spec and not as an extension method offered by us.

The spec is not marked stable for the Exceptions part.!

@cijothomas
Copy link
Member

I didn't reach for TagList is that it is not used by any of the existing Activity APIs (might fact check me on this...)

IIRC, TagList was added while adding Metrics. It was intentionally not placed in .Metrics namespace, to re-use it in the future for Tracing as well. Its something we need to ask to be supported by StartActivity overloads. (We have a good use-case now - spec is recommending to add all available attributes at span creation. One good way to do it alloc-free would be to add more overloads to StartActivity, accepting TagList...

@CodeBlanch
Copy link
Member

I agree with the benefits, but I guess the reason I didn't reach for TagList is that it is not used by any of the existing Activity APIs

Ya like @cijothomas said I think that is just because it came later 😄

Also, one might argue that RecordException should be offered by .NET itself since it is part of the spec and not as an extension method offered by us.

I think someday it will get there 😄 dotnet/runtime#53641

TagList implements IEnumerable<KeyValuePair<string, object>>, so it could still be used - albeit not with the sugary syntax. Could RecordException do a tags is TagList enumerateMeForFree to get the perf benefit? I guess there's probably a boxing in passing it to RecordException, but then would there still be a benefit when enumerating?

You mean have the method accept the interface and let user pass in TagList if they so-desire? Yes, possible, but allocates + copies so probably worse for perf!

If you made it RecordException<T>(Exception ex, T tags) where T : IEnumerable<KeyValuePair<string, object>> you could probably avoid the boxing and then use is TagList in the implementation to avoid the enumerator.

@alanwest
Copy link
Member Author

The spec is not marked stable for the Exceptions part.!

and

I think someday it will get there 😄 dotnet/runtime#53641

Understood - though wasn't aware of the already open issue. The thing I was unsure of was whether once it was part of the Activity API what type would be used. Sounds like it's expected that TagList will be used. If so, then yes makes complete sense to use TagList.

@@ -92,6 +104,11 @@ public static void RecordException(this Activity activity, Exception ex)
tagsCollection.Add(SemanticConventions.AttributeExceptionMessage, ex.Message);
}

foreach (var tag in tags)
Copy link
Contributor

Choose a reason for hiding this comment

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

Add a null check for activity in the beginning to return if the activity is null and avoid creating tagsCollection and copying from tagList.

Copy link
Member Author

Choose a reason for hiding this comment

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

Added null check.

This brought my attention to a somewhat interesting question: what if ex is null, but tags is not?

One might argue that the only reason someone would call RecordException is if they had a non-null exception and that if they just wanted to add an event then they'd call Activity.AddEvent.

But what do folks think? Should we add an event anyways even though no exception related attributes may end up on the event?

Copy link
Contributor

Choose a reason for hiding this comment

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

Should we add an event anyways even though no exception related attributes may end up on the event?

It doesn't sound right to me. I assume most people would use this in the catch block or some callback for when an exception occurs. So, it should not be a common scenario. I would say, as you mentioned, they should just use Activity.AddEvent if it has nothing to do with an actual exception.

Copy link
Contributor

@utpilla utpilla left a comment

Choose a reason for hiding this comment

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

Left a suggestion. Looks good overall.

/// <param name="ex">Exception to be recorded.</param>
/// <param name="tags">Additional tags to record on the event.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void RecordException(this Activity activity, Exception ex, in TagList tags)
Copy link
Member

Choose a reason for hiding this comment

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

unless Activity.AddEvent/team also accepts TagList, the benefits of using TagList in this API is nil, as we anyway have to allocate the ActivityTagsCollection.

Hopefully if/when the spec is stable, we can bring this up.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think the idea is that the consumer can still avoid some allocations when using TagList, but yea the benefit would be greater if AddEvent accepted TagList as well.

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.

Please update the PR description with the final shape of the API.

@alanwest alanwest merged commit 5c9a5c6 into open-telemetry:main Jul 19, 2022
@alanwest alanwest deleted the alanwest/record-exception branch July 19, 2022 21:57
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.

RecordException needs to allow for adding additional event attributes
4 participants