/// <summary> /// Get the specific metric for a given label. /// /// If a set of acceptable labels were specified in the metrics.yaml file, /// and the given label is not in the set, it will be recorded under the /// special `__other__`. /// /// If a set of acceptable labels was not specified in the metrics.yaml file, /// only the first 16 unique labels will be used. After that, any additional /// labels will be recorded under the special `__other__` label. /// /// Labels must be snake_case and less than 30 characters. If an invalid label /// is used, the metric will be recorded in the special `__other__` label. /// </summary> /// <param name="label">The label</param> /// <exception cref="InvalidOperationException"> /// If the type of `T` is currently not supported. /// </exception> public T this[string label] { get { // Note the double `(T)(ILabeledSubmetricInterface)` cast before returning. This is // required in order to make the compiler not complain. Since the `where` clause for // this class cannot list more than one class, we need all our supported subtypes to // implement a common interface and use that interface as the T type constraint. This // allows us to then explicitly cast back to T, which is otherwise impossible. switch (submetric) { case BooleanMetricType _: { UInt64 handle = LibGleanFFI.glean_labeled_boolean_metric_get(this.handle, label); return((T)(ILabeledSubmetricInterface) new BooleanMetricType(handle, disabled, sendInPings)); } case CounterMetricType _: { UInt64 handle = LibGleanFFI.glean_labeled_counter_metric_get(this.handle, label); return((T)(ILabeledSubmetricInterface) new CounterMetricType(handle, disabled, sendInPings)); } case StringMetricType _: { UInt64 handle = LibGleanFFI.glean_labeled_string_metric_get(this.handle, label); return((T)(ILabeledSubmetricInterface) new StringMetricType(handle, disabled, sendInPings)); } default: throw new InvalidOperationException("Can not get a submetric of this metric type"); } } }