Skip to content

System.Diagnostics Tracing APIs (#35220)#35326

Merged
tarekgh merged 1 commit into
dotnet:release/5.0-preview4from
tarekgh:release/5.0-preview4
Apr 23, 2020
Merged

System.Diagnostics Tracing APIs (#35220)#35326
tarekgh merged 1 commit into
dotnet:release/5.0-preview4from
tarekgh:release/5.0-preview4

Conversation

@tarekgh
Copy link
Copy Markdown
Member

@tarekgh tarekgh commented Apr 23, 2020

This change is porting the added System.Diagnostics APIs to preview 4. These APIs are very important to fill the gap between .NET Libraries and OpenTelemtry. There are some teams (application insight and Azure Monitoring) waiting to try the new APIs as early as we can provide it. It will be good if we can have these APIs included in preview 4 for early adaptors.

Original PR merged to master: #35220
Original issue tracking the work: #31373
The design issue for the APIs: dotnet/designs#98

CC @noahfalk

* System.Diagnostics Tracing APIs

* address the feedback
@Dotnet-GitSync-Bot
Copy link
Copy Markdown
Collaborator

Note regarding the new-api-needs-documentation label:

This serves as a reminder for when your PR is modifying a ref *.cs file and adding/modifying public APIs, to please make sure the API implementation in the src *.cs file is documented with triple slash comments, so the PR reviewers can sign off that change.

@ghost
Copy link
Copy Markdown

ghost commented Apr 23, 2020

Tagging subscribers to this area: @tarekgh, @tommcdon
Notify danmosemsft if you want to be subscribed.

@tarekgh tarekgh added the Servicing-consider Issue for next servicing release review label Apr 23, 2020
@tarekgh tarekgh added this to the 5.0 milestone Apr 23, 2020
@tarekgh
Copy link
Copy Markdown
Member Author

tarekgh commented Apr 23, 2020

@ericstj @Anipik please let me know if there is anything else I should do to get this to preview 4. Thanks!

private static readonly IEnumerable<ActivityLink> s_emptyLinks = new ActivityLink[0];
private static readonly IEnumerable<ActivityEvent> s_emptyEvents = new ActivityEvent[0];
#pragma warning restore CA1825
private static ActivitySource s_defaultSource = new ActivitySource(string.Empty);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
private static ActivitySource s_defaultSource = new ActivitySource(string.Empty);
private static readonly ActivitySource s_defaultSource = new ActivitySource(string.Empty);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'll do that.

private string? _displayName;

/// <summary>
/// Kind describes the relationship between the Activity, its parents, and its children in a Trace.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/// Kind describes the relationship between the Activity, its parents, and its children in a Trace.
/// Gets or sets the relationship between the Activity, its parents, and its children in a Trace.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'll do that.

Comment on lines +97 to +100
/// <summary>
/// DisplayName is name mainly intended to be used in the UI and not necessary has to be
/// same as OperationName.
/// </summary>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/// <summary>
/// DisplayName is name mainly intended to be used in the UI and not necessary has to be
/// same as OperationName.
/// </summary>
/// <summary>Gets or sets the display name of the Activity</summary>
/// <remarks>
/// DisplayName is intended to be used in a user interface and need not be the same as OperationName.
/// </remarks>

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'll do that.

public string DisplayName
{
get => _displayName ?? OperationName;
set => _displayName = value;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is null expected / allowed? If you want to permit null, you should add [AllowNull] to the property. If you don't want to permit null, ideally this would throw, e.g. set => _displayName = value ?? throw new ArgumentNullException(nameof(value));

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'll change this to
set => _displayName = value ?? throw new ArgumentNullException(nameof(value));

Comment on lines +107 to +111
/// <summary>
/// Get the ActivitySource object associated with this Activity.
/// All Activities created from public constructors will have a singleton source where the source name is empty string.
/// Otherwise, the source will be holding the object that created the Activity through ActivitySource.StartActivity.
/// </summary>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/// <summary>
/// Get the ActivitySource object associated with this Activity.
/// All Activities created from public constructors will have a singleton source where the source name is empty string.
/// Otherwise, the source will be holding the object that created the Activity through ActivitySource.StartActivity.
/// </summary>
/// <summary>Get the ActivitySource object associated with this Activity.</summary>
/// <remarks>
/// All Activities created from public constructors will have a singleton source where the source name is an empty string.
/// Otherwise, the source will hold the object that created the Activity through ActivitySource.StartActivity.
/// </remarks>

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I'll do that

private static SynchronizedList<ActivityListener> s_allListeners = new SynchronizedList<ActivityListener>();
private SynchronizedList<ActivityListener>? _listeners;

private ActivitySource() { throw new InvalidOperationException(); }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why is this needed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I left it when I was doing some internal testing. It was not intended to stay. Thanks for the catch.

// Causion: We can have the action executed on the same item more than once which is ok in our scenarios.
internal class SynchronizedList<T>
{
private List<T> _list;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
private List<T> _list;
private readonly List<T> _list;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

will do it.

// SynchronizedList<T> is a helper collection which ensure thread safety on the collection
// and allow enumerating the collection items and execute some action on the enumerated item and can detect any change in the collection
// during the enumeration which force restarting the enumeration again.
// Causion: We can have the action executed on the same item more than once which is ok in our scenarios.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// Causion: We can have the action executed on the same item more than once which is ok in our scenarios.
// Caution: We can have the action executed on the same item more than once which is ok in our scenarios.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

why English lack having Causion :-) interesting the editor spell checker didn't complain. of course, I'll fix it. thanks.

{
lock (_list)
{
if (!_list.Contains(item))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

How big do we expect these lists to be? And more importantly, what's the worst case? N calls to AddIfNotExist results in O(N^2) work here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

We are expecting the lists to be short. For activity sources, we expect would be one per component if the component publishing any tracing data. For the listeners, usually, the list will be shorter as in main scenario cases we expect one listener for who is interested to get the Activity notification (e.g. OpenTelemetry for instance). usual apps/Libraries not going to create listeners.

{
version = _version;
index = 0;
continue;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So if there's a mutation we start over? Hence the warning about potentially invoking delegates multiple times? This means if one bad actor was repeatedly adding / removing / adding / removing / etc. while someone else was enumerating, that someone else might never end?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, it is safe in the calling scenarios. We are calling the listeners to detect if we need to create the Activity. I am not seeing a problem calling the listener multiple times with the same parameters multiple parameters when someone else mutates the list.
The lists we have are the ActivtySource lists and listeners inside the activity source. If there is a bad actor you can do many more bad things creating a lot of Activity sources and listeners. or even in the listening can spend a long time in the execution.

@tarekgh
Copy link
Copy Markdown
Member Author

tarekgh commented Apr 23, 2020

@stephentoub could you please tell which of your comments should block getting this to preview 4? I am asking because I can address your comments on master instead and safely catch preview 4.

@stephentoub
Copy link
Copy Markdown
Member

I didn't realize this was already merged to master.

It'd be good to at least reason about the last two comments.

@danmoseley danmoseley added Servicing-approved Approved for servicing release and removed Servicing-consider Issue for next servicing release review labels Apr 23, 2020
@danmoseley
Copy link
Copy Markdown
Member

Approved for P4, merging today would be ideal -- cc @Anipik

@tarekgh
Copy link
Copy Markdown
Member Author

tarekgh commented Apr 23, 2020

Talked to @stephentoub offline and learned none of the feedback comments is P4 blocker. So, I'll go ahead and merge this one and will address the feedback on the master. Thanks, @stephentoub for the feedback.

@tarekgh tarekgh merged commit 88c069b into dotnet:release/5.0-preview4 Apr 23, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 9, 2020
@tarekgh tarekgh deleted the release/5.0-preview4 branch March 15, 2021 19:41
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants