/// <summary>
        /// Times a step with specified key.
        /// </summary>
        /// <param name="profiler">The profiler.</param>
        /// <param name="key">The key.</param>
        /// <param name="reporter">Action to report result.</param>
        /// <returns></returns>
        public static IDisposable Step(this MetricsPipe profiler, string key, Action <MetricsPipe, string, long> reporter)
        {
            if (profiler == null)
            {
                return(null);
            }

            if (reporter == null)
            {
                throw new ArgumentNullException("reporter");
            }

            var timing = profiler.StartTiming();

            return(new Reporter(() =>
            {
                timing.Dispose();

                int?elapsed = timing.ComputeElapsedMilliseconds();

                if (elapsed.HasValue)
                {
                    reporter(profiler, key, elapsed.Value);
                }
            }));
        }
        /// <summary>
        /// Times a step with specified key.
        /// </summary>
        /// <param name="profiler">The profiler.</param>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        public static IDisposable Step(this MetricsPipe profiler, string key)
        {
            if (profiler == null)
            {
                return(null);
            }

            var timing = profiler.StartTiming();

            return(new Reporter(() =>
            {
                timing.Dispose();

                int?elapsed = timing.ComputeElapsedMilliseconds();

                if (elapsed.HasValue)
                {
                    profiler.ReportTiming(key, elapsed.Value);
                }
            }));
        }