Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public sealed class ObservableCounter<T> : ObservableInstrument<T> where T : str
{
private readonly object _callback;

internal override object? Callback => _callback;

internal ObservableCounter(Meter meter, string name, Func<T> observeValue, string? unit, string? description) : this(meter, name, observeValue, unit, description, tags: null)
{
}
Expand Down Expand Up @@ -50,6 +52,6 @@ internal ObservableCounter(Meter meter, string name, Func<IEnumerable<Measuremen
/// <summary>
/// Observe() fetches the current measurements being tracked by this observable counter.
/// </summary>
protected override IEnumerable<Measurement<T>> Observe() => Observe(_callback);
protected override IEnumerable<Measurement<T>> Observe() => ((Func<IEnumerable<Measurement<T>>>)_callback)();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public sealed class ObservableGauge<T> : ObservableInstrument<T> where T : struc
{
private readonly object _callback;

internal override object? Callback => _callback;

internal ObservableGauge(Meter meter, string name, Func<T> observeValue, string? unit, string? description) : this(meter, name, observeValue, unit, description, tags: null)
{
}
Expand Down Expand Up @@ -50,6 +52,6 @@ internal ObservableGauge(Meter meter, string name, Func<IEnumerable<Measurement<
/// <summary>
/// Observe() fetches the current measurements being tracked by this observable counter.
/// </summary>
protected override IEnumerable<Measurement<T>> Observe() => Observe(_callback);
protected override IEnumerable<Measurement<T>> Observe() => ((Func<IEnumerable<Measurement<T>>>)_callback)();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Runtime.CompilerServices;

namespace System.Diagnostics.Metrics
{
Expand Down Expand Up @@ -50,45 +49,45 @@ protected ObservableInstrument(Meter meter, string name, string? unit, string? d
/// </summary>
public override bool IsObservable => true;

// Returns the underlying user callback for built-in observable instruments, or null for user-defined subclasses.
// Subclasses provide their measurements via the abstract Observe() method instead.
internal virtual object? Callback => null;

// Will be called from MeterListener.RecordObservableInstruments for each observable instrument.
internal override void Observe(MeterListener listener)
{
object? state = GetSubscriptionState(listener);

IEnumerable<Measurement<T>> measurements = Observe();
if (measurements is null)
// Fast path for the built-in observable instruments: dispatch their callbacks
// directly to the listener, avoiding the per-observation Measurement<T>[1] allocation that
// the IEnumerable<Measurement<T>> path used to require.
object? callback = Callback;

if (callback is Func<T> valueOnlyFunc)
{
listener.NotifyMeasurement(this, valueOnlyFunc(), Instrument.EmptyTags, state);
return;
}

foreach (Measurement<T> measurement in measurements)
if (callback is Func<Measurement<T>> measurementOnlyFunc)
{
Measurement<T> measurement = measurementOnlyFunc();
listener.NotifyMeasurement(this, measurement.Value, measurement.Tags, state);
}
}

// Will be called from the concrete classes which extends ObservabilityInstrument<T> when calling Observe() method.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static IEnumerable<Measurement<T>> Observe(object callback)
{
if (callback is Func<T> valueOnlyFunc)
{
return new Measurement<T>[1] { new Measurement<T>(valueOnlyFunc()) };
return;
}

if (callback is Func<Measurement<T>> measurementOnlyFunc)
// Func<IEnumerable<Measurement<T>>> built-ins and user-defined ObservableInstrument<T> subclasses
// both fall through to the virtual Observe() override.
IEnumerable<Measurement<T>> measurements = Observe();
if (measurements is null)
{
return new Measurement<T>[1] { measurementOnlyFunc() };
return;
}

if (callback is Func<IEnumerable<Measurement<T>>> listOfMeasurementsFunc)
foreach (Measurement<T> measurement in measurements)
{
return listOfMeasurementsFunc();
listener.NotifyMeasurement(this, measurement.Value, measurement.Tags, state);
}

Debug.Fail("Execution shouldn't reach this point");
return null;
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public sealed class ObservableUpDownCounter<T> : ObservableInstrument<T> where T
{
private readonly object _callback;

internal override object? Callback => _callback;

internal ObservableUpDownCounter(Meter meter, string name, Func<T> observeValue, string? unit, string? description) : this(meter, name, observeValue, unit, description, tags: null)
{
}
Expand Down Expand Up @@ -50,6 +52,6 @@ internal ObservableUpDownCounter(Meter meter, string name, Func<IEnumerable<Meas
/// <summary>
/// Observe() fetches the current measurements being tracked by this observable counter.
/// </summary>
protected override IEnumerable<Measurement<T>> Observe() => Observe(_callback);
protected override IEnumerable<Measurement<T>> Observe() => ((Func<IEnumerable<Measurement<T>>>)_callback)();
}
}
Loading