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

[System.Diagnostics.DiagnosticSource] Implement metrics advice API #102524

Open
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

CodeBlanch
Copy link
Contributor

Copy link

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, 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.

@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label May 21, 2024
@CodeBlanch CodeBlanch marked this pull request as ready for review May 21, 2024 21:16
@tarekgh tarekgh self-assigned this May 21, 2024
@tarekgh tarekgh added this to the 9.0.0 milestone May 21, 2024
@tarekgh
Copy link
Member

tarekgh commented May 21, 2024

CC @noahfalk

Copy link
Member

@tarekgh tarekgh left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks @CodeBlanch for providing the implementation.

@CodeBlanch CodeBlanch marked this pull request as draft June 4, 2024 17:53
/// Contains configuration settings advised to be used by metrics consumers when recording measurements for a given <see cref="Instrument{T}"/>.
/// </summary>
/// <typeparam name="T">Instrument value type.</typeparam>
public sealed class InstrumentAdvice<T> where T : struct
Copy link
Member

Choose a reason for hiding this comment

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

public sealed class InstrumentAdvice where T : struct

I think we need a parameter-less constructor here and inside it we need to call Instrument.ValidateTypeParameter<T>()

https://github.com/dotnet/runtime/blob/29f3110fc971c8cc48f18956d347e58c54bd0639/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Instrument.cs#L141C30-L141C38

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated

Copy link
Member

Choose a reason for hiding this comment

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

do we need to add the constructor to the ref file too src\libraries\System.Diagnostics.DiagnosticSource\ref\System.Diagnostics.DiagnosticSourceActivity.cs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It doesn't complain without it so maybe it is an implied thing? I went ahead and added it though.

Copy link
Member

Choose a reason for hiding this comment

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

Right. the compiler automatically generates the parameter-less constructor. So, it implicitly existed in the ref too. It is good to explicitly list it as we add some code there.

@tarekgh
Copy link
Member

tarekgh commented Jun 11, 2024

CC @noahfalk if need to take one final look before we merge.

Copy link
Member

@noahfalk noahfalk left a comment

Choose a reason for hiding this comment

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

I've still got concerns about the 'init' keyword :)

public IReadOnlyList<T>? HistogramBucketBoundaries
{
get => _HistogramBucketBoundaries;
init
Copy link
Member

Choose a reason for hiding this comment

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

I've still got concerns about 'init' due to the difficulty invoking it from .NET Framework while using the officially supported 7.3 C# language version. Maybe in the future we'll decide to drop support for .NET Framework but we've not agreed to that so far.

I maintain the suggestion to define this property with as 'set', not 'init' and if we want to protect against mutations then we can make a read-only copy.

Copy link
Member

@tarekgh tarekgh Jun 12, 2024

Choose a reason for hiding this comment

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

I humbly disagree. As I mentioned before, doing the allocation and copying is not good IMO especially we need to maintain that in the future too. We discussed that in the design review and didn't get any objection. Also, init is already used in the same library too.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The code as-is already takes a copy of the data 😄 The issue I think set creates is more that it can't be changed after the first publish of a metric. What OTel is going to do is on instrument published take the advice and construct the buckets after which point they are fixed. So having the set could just be misleading for users thinking they can set it whenever. init really conveys the meaning nicely for what this class is doing.

I guess we could have set throw based on some internal state tracking if the thing was published? But then what if you hand the same advice class to multiple instruments? 🤔

/// Contains configuration settings advised to be used by metrics consumers when recording measurements for a given <see cref="Instrument{T}"/>.
/// </summary>
/// <typeparam name="T">Instrument value type.</typeparam>
public sealed class InstrumentAdvice<T> where T : struct
Copy link
Member

Choose a reason for hiding this comment

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

Why must T be a value type?

Copy link
Member

Choose a reason for hiding this comment

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

Oh, I see, it's not that it needs to be a value type, it's that it must be just one of byte, short, int, long, double, float, or decimal. Do we use such a constraint in other places for the same purpose?

Copy link
Member

@tarekgh tarekgh Jun 12, 2024

Choose a reason for hiding this comment

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

We support only specific set of types

internal static void ValidateTypeParameter<T>()
{
Type type = typeof(T);
if (type != typeof(byte) && type != typeof(short) && type != typeof(int) && type != typeof(long) &&
type != typeof(double) && type != typeof(float) && type != typeof(decimal))
{
throw new InvalidOperationException(SR.Format(SR.UnsupportedType, type));
}
}

The supported T types in the advice class should exactly match the same supported types in Instrument<T>. Metrics work only with numerical types.

Copy link
Member

Choose a reason for hiding this comment

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

Do we use such a constraint in other places for the same purpose?

I am not aware of other places other than metrics. @tannergooding may know if there are other places that apply similar restrictions.

Copy link
Member

Choose a reason for hiding this comment

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

But we already use the same constraint for the same limited set of types elsewhere in metrics?

Copy link
Member

@noahfalk noahfalk Jun 12, 2024

Choose a reason for hiding this comment

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

But we already use the same constraint for the same limited set of types elsewhere in metrics?

Correct. For Instrument<T> we do the same type validation here:
https://github.com/dotnet/runtime/blob/main/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Metrics/Instrument.common.cs#L40

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-System.Diagnostics.Metric community-contribution Indicates that the PR has been added by a community member new-api-needs-documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add "hints" in Metric API to provide things like histogram bounds
5 participants