Instrument
Base class of all metrics instrument classes
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace System.Diagnostics.Metrics
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public abstract class Instrument
{
internal readonly DiagLinkedList<ListenerSubscription> _subscriptions = new DiagLinkedList<ListenerSubscription>();
[System.Runtime.CompilerServices.Nullable(new byte[] {
1,
0,
1,
2
})]
internal static KeyValuePair<string, object>[] EmptyTags {
get {
return Array.Empty<KeyValuePair<string, object>>();
}
}
internal static object SyncObject { get; } = new object();
public Meter Meter { get; }
public string Name { get; }
[System.Runtime.CompilerServices.Nullable(2)]
public string Description {
[System.Runtime.CompilerServices.NullableContext(2)]
get;
}
[System.Runtime.CompilerServices.Nullable(2)]
public string Unit {
[System.Runtime.CompilerServices.NullableContext(2)]
get;
}
[System.Runtime.CompilerServices.Nullable(new byte[] {
2,
0,
1,
2
})]
public IEnumerable<KeyValuePair<string, object>> Tags {
[return: System.Runtime.CompilerServices.Nullable(new byte[] {
2,
0,
1,
2
})]
get;
}
public bool Enabled => _subscriptions.First != null;
public virtual bool IsObservable => false;
protected Instrument(Meter meter, string name)
: this(meter, name, null, null, null)
{
}
[EditorBrowsable(EditorBrowsableState.Never)]
protected Instrument(Meter meter, string name, [System.Runtime.CompilerServices.Nullable(2)] string unit, [System.Runtime.CompilerServices.Nullable(2)] string description)
: this(meter, name, unit, description, null)
{
}
protected Instrument(Meter meter, string name, [System.Runtime.CompilerServices.Nullable(2)] string unit = null, [System.Runtime.CompilerServices.Nullable(2)] string description = null, [System.Runtime.CompilerServices.Nullable(new byte[] {
2,
0,
1,
2
})] IEnumerable<KeyValuePair<string, object>> tags = null)
{
if (meter == null)
throw new ArgumentNullException("meter");
Meter = meter;
if (name == null)
throw new ArgumentNullException("name");
Name = name;
Description = description;
Unit = unit;
if (tags != null) {
List<KeyValuePair<string, object>> list = new List<KeyValuePair<string, object>>(tags);
list.Sort((KeyValuePair<string, object> left, KeyValuePair<string, object> right) => string.Compare(left.Key, right.Key, StringComparison.Ordinal));
Tags = list;
}
}
protected void Publish()
{
if (Meter.IsSupported) {
List<MeterListener> list = null;
lock (SyncObject) {
if (Meter.Disposed || !Meter.AddInstrument(this))
return;
list = MeterListener.GetAllListeners();
}
if (list != null) {
foreach (MeterListener item in list) {
item.InstrumentPublished?.Invoke(this, item);
}
}
}
}
internal void NotifyForUnpublishedInstrument()
{
for (DiagNode<ListenerSubscription> diagNode = _subscriptions.First; diagNode != null; diagNode = diagNode.Next) {
diagNode.Value.Listener.DisableMeasurementEvents(this);
}
_subscriptions.Clear();
}
internal static void ValidateTypeParameter<T>()
{
Type typeFromHandle = typeof(T);
if (typeFromHandle != typeof(byte) && typeFromHandle != typeof(short) && typeFromHandle != typeof(int) && typeFromHandle != typeof(long) && typeFromHandle != typeof(double) && typeFromHandle != typeof(float) && typeFromHandle != typeof(decimal))
throw new InvalidOperationException(System.SR.Format(System.SR.UnsupportedType, typeFromHandle));
}
internal object EnableMeasurement(ListenerSubscription subscription, out bool oldStateStored)
{
oldStateStored = false;
if (!_subscriptions.AddIfNotExist(subscription, (ListenerSubscription s1, ListenerSubscription s2) => s1.Listener == s2.Listener)) {
ListenerSubscription listenerSubscription = _subscriptions.Remove(subscription, (ListenerSubscription s1, ListenerSubscription s2) => s1.Listener == s2.Listener);
_subscriptions.AddIfNotExist(subscription, (ListenerSubscription s1, ListenerSubscription s2) => s1.Listener == s2.Listener);
oldStateStored = (listenerSubscription.Listener == subscription.Listener);
return listenerSubscription.State;
}
return false;
}
internal object DisableMeasurements(MeterListener listener)
{
return _subscriptions.Remove(new ListenerSubscription(listener, null), (ListenerSubscription s1, ListenerSubscription s2) => s1.Listener == s2.Listener).State;
}
internal virtual void Observe(MeterListener listener)
{
throw new InvalidOperationException();
}
internal object GetSubscriptionState(MeterListener listener)
{
for (DiagNode<ListenerSubscription> diagNode = _subscriptions.First; diagNode != null; diagNode = diagNode.Next) {
if (listener == diagNode.Value.Listener)
return diagNode.Value.State;
}
return null;
}
}
}