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

Support Metrics UpDownCounter instrument #63648

Closed
Tracked by #62027
tarekgh opened this issue Jan 11, 2022 · 2 comments · Fixed by #64365
Closed
Tracked by #62027

Support Metrics UpDownCounter instrument #63648

tarekgh opened this issue Jan 11, 2022 · 2 comments · Fixed by #64365
Assignees
Labels
api-approved API was approved in API review, it can be implemented area-System.Diagnostics.Metric
Milestone

Comments

@tarekgh
Copy link
Member

tarekgh commented Jan 11, 2022

Background and motivation

In .NET 6.0 we have exposed the Metric APIs with exposing different instrument types Counter, Histogram, ObservableCounter, and ObservableGauge. We didn't expose the remaining instruments UpDownCounter and ObservableUpDownCounter. We were collecting feedback to see the demand and the scenarios needed for such instruments before exposing it. Also, we were waiting to have OpenTelemetry specs marked as stable too.

Now we have the feedback, and we are seeing the demand for such instruments and the scenarios need such instruments. The proposal here is to expose these instruments.

OpenTelemetry specification
open-telemetry/opentelemetry-dotnet#2362

APIs Proposal

UpDownCounter and ObservableUpDownCounter support only the following generic parameter types: Byte, Int16, Int32, Int64, Single, Double, and Decimal.

namespace System.Diagnostics.Metrics
{
    public sealed class UpDownCounter<T> : Instrument<T> where T : struct
    {
        public void Add(T delta) {  throw null; }
        public void Add(T delta, KeyValuePair<string, object?> tag)  {  throw null; }
        public void Add(T delta, KeyValuePair<string, object?> tag1, KeyValuePair<string, object?> tag2)  {  throw null; }
        public void Add(T delta, KeyValuePair<string, object?> tag1, KeyValuePair<string, object?> tag2, KeyValuePair<string, object?> tag3)  {  throw null; }
        public void Add(T delta, ReadOnlySpan<KeyValuePair<string, object?>> tags) {  throw null; }
        public void Add(T delta, params KeyValuePair<string, object?>[] tags) {  throw null; }
        public void Add(T delta, in TagList tagList) { throw null; }
    }

    public sealed class ObservableUpDownCounter<T> : ObservableInstrument<T> where T : struct
    {
        protected override IEnumerable<Measurement<T>> Observe() { throw null;}
    }

    public class Meter : IDisposable
    {
        public UpDownCounter<T> CreateUpDownCounter<T>(string name, string? unit = null, string? description = null) where T : struct  { throw null; }
        
        public ObservableUpDownCounter<T> CreateObservableUpDownCounter<T>(
                            string name,
                            Func<T> observeValue,
                            string? unit = null,
                            string? description = null) where T : struct { throw null; }
        public ObservableUpDownCounter<T> CreateObservableUpDownCounter<T>(
                            string name,
                            Func<Measurement<T>> observeValue,
                            string? unit = null,
                            string? description = null) where T : struct { throw null; }
        public ObservableUpDownCounter<T> CreateObservableUpDownCounter<T>(
                            string name,
                            Func<IEnumerable<Measurement<T>>> observeValues,
                            string? unit = null,
                            string? description = null) where T : struct { throw null; }        
    }
}

APIs Usage

static Meter s_meter = new Meter("MyLibrary.Queues", "1.0.0");

static UpDownCounter<int> s_queueSize = s_meter.CreateUpDownCounter<int>("Queue-Size");

static ObservableUpDownCounter<int> s_pullQueueSize = s_meter.CreateObservableUpDownCounter<int>("Queue-Size", () => s_pullQueueSize);

...

s_queueSize.Add(10);
s_queueSize.Add(-2);
@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Jan 11, 2022
@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@tarekgh tarekgh added area-System.Diagnostics.Metric feature-request and removed untriaged New issue has not been triaged by the area owner labels Jan 11, 2022
@tarekgh tarekgh added this to the 7.0.0 milestone Jan 11, 2022
@tarekgh tarekgh added api-needs-work API needs work before it is approved, it is NOT ready for implementation and removed feature-request labels Jan 19, 2022
@tarekgh tarekgh self-assigned this Jan 19, 2022
@tarekgh tarekgh added api-ready-for-review API is ready for review, it is NOT ready for implementation and removed api-needs-work API needs work before it is approved, it is NOT ready for implementation labels Jan 24, 2022
@terrajobst
Copy link
Member

terrajobst commented Jan 25, 2022

Video

  • We considered using generic math to constrain the T, to, for example, INumber but the list of types are taken from the OpenTelemetry spec
  • UpDownCounter and ObservableUpDownCounter support only the following generic parameter types: Byte, Int16, Int32, Int64, Single, Double, and Decimal.

    • Should we consider supporting unsigned types?
    • Should we drop byte?
    • We should strive for consistency with what we shipped before for Counter (if we support byte there, we should do it here too)
    • We can consider adding support for unsigned types later too
namespace System.Diagnostics.Metrics
{
    public sealed class UpDownCounter<T> : Instrument<T> where T : struct
    {
        public void Add(T delta);
        public void Add(T delta, KeyValuePair<string, object?> tag);
        public void Add(T delta, KeyValuePair<string, object?> tag1, KeyValuePair<string, object?> tag2);
        public void Add(T delta, KeyValuePair<string, object?> tag1, KeyValuePair<string, object?> tag2, KeyValuePair<string, object?> tag3);
        public void Add(T delta, ReadOnlySpan<KeyValuePair<string, object?>> tags);
        public void Add(T delta, params KeyValuePair<string, object?>[] tags);
        public void Add(T delta, in TagList tagList);
    }
    public sealed class ObservableUpDownCounter<T> : ObservableInstrument<T> where T : struct
    {
        protected override IEnumerable<Measurement<T>> Observe();
    }
    public partial class Meter : IDisposable
    {
        public UpDownCounter<T> CreateUpDownCounter<T>(string name, string? unit = null, string? description = null) where T : struct ;
        public ObservableUpDownCounter<T> CreateObservableUpDownCounter<T>(
                            string name,
                            Func<T> observeValue,
                            string? unit = null,
                            string? description = null) where T : struct;
        public ObservableUpDownCounter<T> CreateObservableUpDownCounter<T>(
                            string name,
                            Func<Measurement<T>> observeValue,
                            string? unit = null,
                            string? description = null) where T : struct;
        public ObservableUpDownCounter<T> CreateObservableUpDownCounter<T>(
                            string name,
                            Func<IEnumerable<Measurement<T>>> observeValues,
                            string? unit = null,
                            string? description = null) where T : struct;
    }
}

@terrajobst terrajobst added api-approved API was approved in API review, it can be implemented and removed api-ready-for-review API is ready for review, it is NOT ready for implementation labels Jan 25, 2022
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Jan 27, 2022
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Jan 28, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Feb 27, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-approved API was approved in API review, it can be implemented area-System.Diagnostics.Metric
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants