/// <summary>
        /// Abort a previous `Start` call. No error is recorded if no `Start` was called.
        /// </summary>
        /// <param name="timerId">
        /// The `GleanTimerId` associated with this timing. This allows for concurrent timing
        /// of events associated with different ids to the same timing distribution metric.
        /// </param>
        public void Cancel(GleanTimerId timerId)
        {
            if (disabled || timerId == null)
            {
                return;
            }

            Dispatchers.LaunchAPI(() =>
            {
                LibGleanFFI.glean_timing_distribution_cancel(handle, timerId);
            });
        }
        ///<summary>
        /// Convenience method to simplify measuring a function or block of code
        ///
        /// If the measured function throws, the measurement is canceled and the exception rethrown.
        /// </summary>
        /// <exception>
        /// If the measured function throws, the measurement is
        /// canceled and the exception rethrown.
        /// </exception>
        public T Measure <T>(Func <T> funcToMeasure)
        {
            GleanTimerId timerId = Start();

            T returnValue;

            try
            {
                returnValue = funcToMeasure();
            }
            catch (Exception e)
            {
                Cancel(timerId);
                throw e;
            }

            StopAndAccumulate(timerId);

            return(returnValue);
        }
        /// <summary>
        /// Stop tracking time for the provided metric and associated timer id. Add a
        /// count to the corresponding bucket in the timing distribution.
        /// This will record an error if no `Start` was called.
        /// </summary>
        /// <param name="timerId">
        /// The `GleanTimerId` associated with this timing.  This allows for concurrent
        /// timing of events associated with different ids to the same timing distribution.
        /// </param>
        public void StopAndAccumulate(GleanTimerId timerId)
        {
            // `Start` might return null.
            // Accepting that means users of this API don't need to do a null check.
            if (disabled || timerId == null)
            {
                return;
            }

            // The Rust code runs async and might be delayed. We need the time as precise as possible.
            // We also need the same clock for start and stop (`Start` takes the time on the C# side).
            ulong stopTime = HighPrecisionTimestamp.GetTimestamp(TimeUnit.Nanosecond);

            Dispatchers.LaunchAPI(() =>
            {
                LibGleanFFI.glean_timing_distribution_set_stop_and_accumulate(
                    handle,
                    timerId,
                    stopTime
                    );
            });
        }