public NancyAdapterGlobalMetrics()
        {
            this.clock = new TestClock();
            this.scheduler = new TestScheduler(clock);

            this.timer = new TimerMetric(SamplingType.SlidingWindow, new MeterMetric(clock, scheduler), clock);
            this.meter = new MeterMetric(clock, scheduler);
            this.counter = new CounterMetric();
            this.size = new HistogramMetric();

            this.browser = new Browser(with =>
            {
                with.ApplicationStartup((c, p) =>
                {
                    Metric.Config.WithNancy(new TestRegistry
                    {
                        TimerInstance = timer,
                        MeterInstance = meter,
                        CounterInstance = counter,
                        HistogramInstance = size
                    }, nancy => nancy.WithGlobalMetrics(config => config.RegisterAllMetrics(p)));
                });
                with.Module(new TestModule(this.clock));
                with.Module(new ActiveRequestsModule(this.requestTrigger.Task, result1, result2));
            });
        }
        public NancyAdapterGlobalMetrics()
        {
            this.clock     = new TestClock();
            this.scheduler = new TestScheduler(clock);

            this.timer   = new TimerMetric(SamplingType.SlidingWindow, new MeterMetric(clock, scheduler), clock);
            this.meter   = new MeterMetric(clock, scheduler);
            this.counter = new CounterMetric();
            this.size    = new HistogramMetric();

            this.browser = new Browser(with =>
            {
                with.ApplicationStartup((c, p) =>
                {
                    Metric.Config.WithNancy(new TestRegistry
                    {
                        TimerInstance     = timer,
                        MeterInstance     = meter,
                        CounterInstance   = counter,
                        HistogramInstance = size
                    }, nancy => nancy.WithGlobalMetrics(config => config.RegisterAllMetrics(p)));
                });
                with.Module(new TestModule(this.clock));
                with.Module(new ActiveRequestsModule(this.requestTrigger.Task, result1, result2));
            });
        }
 public MetricInfo(string context, string metricName, MetricTags tags, TimerMetric timer, PerfCounterGauge perfCounter)
 {
     this.Context     = context;
     this.MetricName  = metricName;
     this.Tags        = tags;
     this.Timer       = timer;
     this.PerfCounter = perfCounter;
     this.Key         = TagName(this.Context + this.MetricName, this.Tags);
 }
Exemple #4
0
        public void TimerCountsEvenIfActionThrows()
        {
            TimerMetric timer = new TimerMetric();

            Action action = () => timer.Time(() => { throw new InvalidOperationException(); });

            action.ShouldThrow<InvalidOperationException>();

            timer.Value.Rate.Count.Should().Be(1);
        }
Exemple #5
0
        public void TimerCountsEvenIfActionThrows()
        {
            TimerMetric timer = new TimerMetric();

            Action action = () => timer.Time(() => { throw new InvalidOperationException(); });

            action.ShouldThrow <InvalidOperationException>();

            timer.Value.Rate.Count.Should().Be(1);
        }
 private void LogTimer(IRequest request, MetricName metricName, TimerMetric metric, long timestamp)
 {
     LogGauge(request, metricName.Name + "." + TimerMetrics.FifteenMinuteRate.GetDatadogName(), metric.FifteenMinuteRate, timestamp);
     LogGauge(request, metricName.Name + "." + TimerMetrics.FiveMinuteRate.GetDatadogName(), metric.FiveMinuteRate, timestamp);
     LogGauge(request, metricName.Name + "." + TimerMetrics.OneMinuteRate.GetDatadogName(), metric.OneMinuteRate, timestamp);
     LogGauge(request, metricName.Name + "." + TimerMetrics.Max.GetDatadogName(), metric.Max, timestamp);
     LogGauge(request, metricName.Name + "." + TimerMetrics.Mean.GetDatadogName(), metric.Mean, timestamp);
     LogGauge(request, metricName.Name + "." + TimerMetrics.MeanRate.GetDatadogName(), metric.MeanRate, timestamp);
     LogGauge(request, metricName.Name + "." + TimerMetrics.Min.GetDatadogName(), metric.Min, timestamp);
     LogGauge(request, metricName.Name + "." + TimerMetrics.StdDev.GetDatadogName(), metric.StdDev, timestamp);
 }
Exemple #7
0
        public void TimerCanTrackTime()
        {
            TestClock clock = new TestClock();
            TestScheduler scheduler = new TestScheduler(clock);

            TimerMetric timer = new TimerMetric(SamplingType.LongTerm, new MeterMetric(clock, scheduler), clock);
            using (timer.NewContext())
            {
                clock.Advance(TimeUnit.Milliseconds, 100);
            }
            timer.Value.Histogram.Count.Should().Be(1);
            timer.Value.Histogram.Max.Should().Be(TimeUnit.Milliseconds.ToNanoseconds(100));
        }
Exemple #8
0
 public void TimerCanCount()
 {
     TimerMetric timer = new TimerMetric();
     timer.Value.Rate.Count.Should().Be(0);
     using (timer.NewContext()) { }
     timer.Value.Rate.Count.Should().Be(1);
     using (timer.NewContext()) { }
     timer.Value.Rate.Count.Should().Be(2);
     timer.Time(() => { });
     timer.Value.Rate.Count.Should().Be(3);
     timer.Time(() => 1);
     timer.Value.Rate.Count.Should().Be(4);
 }
Exemple #9
0
        private static void AppendTimer(StringBuilder sb, TimerMetric timer)
        {
            sb.Append("{");
            AppendDistribution(sb, timer);

            sb.Append(",\"duration_unit\":\"").Append(timer.DurationUnit).Append("\"")
            .Append(",\"rate_unit\":\"").Append(timer.RateUnit).Append("\"")
            .Append(",\"fifteen_minute_rate\":").Append(timer.FifteenMinuteRate)
            .Append(",\"five_minute_rate\":").Append(timer.FiveMinuteRate)
            .Append(",\"one_minute_rate\":").Append(timer.OneMinuteRate)
            .Append(",\"mean_rate\":").Append(timer.MeanRate);

            sb.Append("}");
        }
        public NancyAdapterModuleMetricsTests()
        {
            this.clock = new TestClock();
            TestScheduler scheduler = new TestScheduler(clock);

            this.timer = new TimerMetric(SamplingType.SlidingWindow, new MeterMetric(clock, scheduler), clock);
            this.sizeHistogram = new HistogramMetric();
            Metric.Config.WithNancy(new TestRegistry { TimerInstance = timer, HistogramInstance = sizeHistogram }, c => { });
            
            this.browser = new Browser(with =>
            {
                with.Module(new TestModule(this.clock));
            });
        }
Exemple #11
0
        public void TimerCanCount()
        {
            TimerMetric timer = new TimerMetric();

            timer.Value.Rate.Count.Should().Be(0);
            using (timer.NewContext()) { }
            timer.Value.Rate.Count.Should().Be(1);
            using (timer.NewContext()) { }
            timer.Value.Rate.Count.Should().Be(2);
            timer.Time(() => { });
            timer.Value.Rate.Count.Should().Be(3);
            timer.Time(() => 1);
            timer.Value.Rate.Count.Should().Be(4);
        }
Exemple #12
0
        public void TimerCanTrackTime()
        {
            TestClock     clock     = new TestClock();
            TestScheduler scheduler = new TestScheduler(clock);

            TimerMetric timer = new TimerMetric(SamplingType.LongTerm, new MeterMetric(clock, scheduler), clock);

            using (timer.NewContext())
            {
                clock.Advance(TimeUnit.Milliseconds, 100);
            }
            timer.Value.Histogram.Count.Should().Be(1);
            timer.Value.Histogram.Max.Should().Be(TimeUnit.Milliseconds.ToNanoseconds(100));
        }
Exemple #13
0
        /// <summary>
        /// Creates a new timer metric and registers it under the given type and name
        /// </summary>
        /// <param name="owner">The type that owns the metric</param>
        /// <param name="name">The metric name</param>
        /// <param name="durationUnit">The duration scale unit of the new timer</param>
        /// <param name="rateUnit">The rate unit of the new timer</param>
        /// <returns></returns>
        public TimerMetric Timer(Type owner, String name, TimeUnit durationUnit, TimeUnit rateUnit)
        {
            var     metricName = new MetricName(owner, name);
            IMetric existingMetric;

            if (_metrics.TryGetValue(metricName, out existingMetric))
            {
                return((TimerMetric)existingMetric);
            }

            var metric          = new TimerMetric(durationUnit, rateUnit);
            var justAddedMetric = _metrics.GetOrAdd(metricName, metric);

            return(justAddedMetric == null ? metric : (TimerMetric)justAddedMetric);
        }
        private MetricInfo RegisterMetric(PdhCounterPathElement pathElement, IDictionary <String, MetricInfo> existingMetrics)
        {
            string contextName  = CleanName(pathElement.ObjectName);
            string metricName   = CleanName(pathElement.CounterName);
            string instanceName = CleanName(pathElement.InstanceName);

            MetricTags tags = default(MetricTags);

            if (instanceName != null)
            {
                tags = "instance=" + instanceName;
            }
            string     keyName = MetricInfo.TagName(contextName + metricName, tags);
            MetricInfo mInfo;

            if (existingMetrics.TryGetValue(keyName, out mInfo))
            {
                existingMetrics.Remove(keyName);
                return(mInfo);
            }

            PerfCounterGauge       pcGauge = new PerfCounterGauge(pathElement.ObjectName, pathElement.CounterName, pathElement.InstanceName);
            TimerMetric            timer   = null;
            PerformanceCounterType type    = pcGauge.performanceCounter.CounterType;

            switch (type)
            {
            //these types of counters are not usable
            case PerformanceCounterType.AverageBase:
            case PerformanceCounterType.CounterMultiBase:
            case PerformanceCounterType.RawBase:
            case PerformanceCounterType.SampleBase:
                _log.Error(String.Format("Don't know how to handle metric of type {0} for {1}", type.ToString(), metricName));
                return(null);

            //timers
            case PerformanceCounterType.AverageTimer32:
            case PerformanceCounterType.ElapsedTime:
                timer = new TimerMetric(SamplingType.FavourRecent);
                break;
            }
            mInfo = new MetricInfo(contextName, metricName, tags, timer, pcGauge);
            if (mInfo.Timer != null)
            {
                _timers[keyName] = mInfo;
            }
            return(mInfo);
        }
Exemple #15
0
        public void TimerContextRecordsTimeOnlyOnFirstDispose()
        {
            TestClock clock = new TestClock();
            TestScheduler scheduler = new TestScheduler(clock);

            TimerMetric timer = new TimerMetric(SamplingType.LongTerm, new MeterMetric(clock, scheduler), clock);

            var context = timer.NewContext();
            clock.Advance(TimeUnit.Milliseconds, 100);
            using (context) { }
            clock.Advance(TimeUnit.Milliseconds, 100);
            using (context) { }

            timer.Value.Histogram.Count.Should().Be(1);
            timer.Value.Histogram.Max.Should().Be(TimeUnit.Milliseconds.ToNanoseconds(100));
        }
        public NancyAdapterModuleMetricsTests()
        {
            this.clock = new TestClock();
            TestScheduler scheduler = new TestScheduler(clock);

            this.timer         = new TimerMetric(SamplingType.SlidingWindow, new MeterMetric(clock, scheduler), clock);
            this.sizeHistogram = new HistogramMetric();
            Metric.Config.WithNancy(new TestRegistry {
                TimerInstance = timer, HistogramInstance = sizeHistogram
            }, c => { });

            this.browser = new Browser(with =>
            {
                with.Module(new TestModule(this.clock));
            });
        }
Exemple #17
0
        public void Can_time_closure()
        {
            var timer  = new TimerMetric(TimeUnit.Seconds, TimeUnit.Seconds);
            var result = timer.Time(() =>
            {
                Thread.Sleep(1);
                return(true);
            });

            Assert.True(result.IsStarted);
            Assert.True(result.IsStopped);
            Assert.True(result.StartedAt.HasValue);
            Assert.True(result.StoppedAt.HasValue);
            Assert.True(result);
            Assert.Equal(1, timer.Count);
            Assert.True(timer.Mean > 0);
        }
Exemple #18
0
        public void TimerContextRecordsTimeOnlyOnFirstDispose()
        {
            TestClock     clock     = new TestClock();
            TestScheduler scheduler = new TestScheduler(clock);

            TimerMetric timer = new TimerMetric(SamplingType.LongTerm, new MeterMetric(clock, scheduler), clock);

            var context = timer.NewContext();

            clock.Advance(TimeUnit.Milliseconds, 100);
            using (context) { }
            clock.Advance(TimeUnit.Milliseconds, 100);
            using (context) { }

            timer.Value.Histogram.Count.Should().Be(1);
            timer.Value.Histogram.Max.Should().Be(TimeUnit.Milliseconds.ToNanoseconds(100));
        }
Exemple #19
0
        public void can_report_timers()
        {
            var expected  = StringReporterSamples.Timers.ExtractStringReporterSampleFromResourceFile();
            var sr        = new StringReporter();
            var clock     = new TestClock();
            var histogram = new HistogramMetric(SamplingType.ExponentiallyDecaying, Constants.ReservoirSampling.DefaultSampleSize,
                                                Constants.ReservoirSampling.DefaultExponentialDecayFactor);
            var metric = new TimerMetric(histogram, clock);

            metric.Record(1000, TimeUnit.Milliseconds, "value1");
            metric.Record(2000, TimeUnit.Milliseconds, "value2");

            sr.ReportMetric("test", new TimerValueSource("timer_name", metric, Unit.None, TimeUnit.Milliseconds,
                                                         TimeUnit.Milliseconds, MetricTags.None));

            AssertReportResult(sr.Result, expected);
        }
        private static void WriteTimer(TextWriter writer, TimerMetric timer)
        {
            WriteMetered(writer, timer);

            var durationUnit = Abbreviate(timer.DurationUnit);

            var percentiles = timer.Percentiles(0.5, 0.75, 0.95, 0.98, 0.99, 0.999);

            writer.Write("               min = %{0:2}{1}\n", timer.Min, durationUnit);
            writer.Write("               max = %{0:2}{1}\n", timer.Max, durationUnit);
            writer.Write("              mean = %{0:2}{1}\n", timer.Mean, durationUnit);
            writer.Write("            stddev = %{0:2}{1}\n", timer.StdDev, durationUnit);
            writer.Write("            median = %{0:2}{1}\n", percentiles[0], durationUnit);
            writer.Write("              75%% <= %{0:2}{1}\n", percentiles[1], durationUnit);
            writer.Write("              95%% <= %{0:2}{1}\n", percentiles[2], durationUnit);
            writer.Write("              98%% <= %{0:2}{1}\n", percentiles[3], durationUnit);
            writer.Write("              99%% <= %{0:2}{1}\n", percentiles[4], durationUnit);
            writer.Write("            99.9%% <= %{0:2}{1}\n", percentiles[5], durationUnit);
        }
        public void can_report_timers()
        {
            var metricsMock = new Mock <IMetrics>();
            var clock       = new TestClock();
            var timer       = new TimerMetric(SamplingType.ExponentiallyDecaying, 1028, 0.015, clock);

            timer.Record(1000, TimeUnit.Milliseconds, "client1");
            var timerValueSource = new TimerValueSource("test timer",
                                                        ConstantValue.Provider(timer.Value), Unit.None, TimeUnit.Milliseconds, TimeUnit.Milliseconds, MetricTags.None);
            var payloadBuilder = new LineProtocolPayloadBuilder();
            var reporter       = CreateReporter(payloadBuilder);

            reporter.StartReportRun(metricsMock.Object);
            reporter.ReportMetric("test", timerValueSource);

            payloadBuilder.PayloadFormatted()
            .Should()
            .Be(
                "test__test_timer count.meter=1i,rate1m=0,rate5m=0,rate15m=0,rate.mean=Infinity,samples=1i,last=1000,count.hist=1i,min=1000,max=1000,mean=1000,median=1000,stddev=0,p999=1000,p99=1000,p98=1000,p95=1000,p75=1000,user.last=\"client1\",user.min=\"client1\",user.max=\"client1\"\n");
        }
Exemple #22
0
        public void SingleTimerTest()
        {
            var         metrics     = new Metrics();
            string      metricName  = "TimerMetric";
            TimerMetric timerMetric = metrics.Timer("test", metricName, TimeUnit.Seconds, TimeUnit.Seconds);

            DataDogReporter reporter = CreateDefaultReporter(metrics);

            TestRequest request = new TestRequest();

            reporter.TransformMetrics(request, metrics, 0);

            IDictionary <string, DatadogSeries> convertedMetrics = request.Metrics;

            Assert.AreEqual(8, convertedMetrics.Count);
            foreach (TimerMetrics timerName in TimerMetrics.AllMetrics)
            {
                DatadogSeries metric = convertedMetrics[APP + "." + DOMAIN + "." + metricName + "." + timerName.GetDatadogName()];
                Assert.NotNull(metric);
                Assert.IsTrue(metric is DatadogGauge);
                ValidateDefaultTags(metric.Tags);
            }
        }
Exemple #23
0
 public TimerMetricTests()
 {
     this.timer = new TimerMetric(new HistogramMetric(new UniformReservoir()), new MeterMetric(this.clock, new TestScheduler(this.clock)), this.clock);
 }
 public TimerMetricTests()
 {
     this.scheduler = new TestScheduler(clock);
     this.timer = new TimerMetric(SamplingType.FavourRecent, new MeterMetric(clock, scheduler), clock);
 }
        public OwinMetricsTestData()
        {
            const int timePerRequest = 100;
            const string json = "{ 'id': '1'} ";

            Clock = new TestClock();
            var scheduler = new TestScheduler(Clock);
            TimerMetric = new TimerMetric(SamplingType.SlidingWindow, new MeterMetric(Clock, scheduler), Clock);
            CounterMetric = new TestCounter();
            HistogramMetric = new HistogramMetric();
            MeterMetric = new MeterMetric(Clock, scheduler);

            var server = TestServer.Create(app =>
            {
                var registery = new TestRegistry
                {
                    TimerInstance = TimerMetric,
                    CounterInstance = CounterMetric,
                    HistogramInstance = HistogramMetric,
                    MeterInstance = MeterMetric
                };

                OwinMetricsConfig owin = new OwinMetricsConfig(middleware => app.Use(middleware), registery, Metric.Config.HealthStatus);
                owin.WithRequestMetricsConfig(c => c.RegisterAllMetrics());

                app.Run(context =>
                {
                    Clock.Advance(TimeUnit.Milliseconds, timePerRequest);
                    if (context.Request.Path.ToString() == "/test/action")
                    {
                        return context.Response.WriteAsync("response");
                    }

                    if (context.Request.Path.ToString() == "/test/error")
                    {
                        context.Response.StatusCode = 500;
                        return context.Response.WriteAsync("response");
                    }

                    if (context.Request.Path.ToString() == "/test/size")
                    {
                        return context.Response.WriteAsync("response");
                    }

                    if (context.Request.Path.ToString() == "/test/post")
                    {
                        return context.Response.WriteAsync("response");
                    }

                    context.Response.StatusCode = 404;
                    return context.Response.WriteAsync("not found");
                });

            });

            ExpectedResults = new OwinExpectedMetrics(timePerRequest, 6, 1);

            server.HttpClient.GetAsync("http://local.test/test/error").Result.StatusCode.Should().Be(HttpStatusCode.InternalServerError);
            server.HttpClient.GetAsync("http://local.test/test/action").Result.StatusCode.Should().Be(HttpStatusCode.OK);
            server.HttpClient.GetAsync("http://local.test/test/action").Result.StatusCode.Should().Be(HttpStatusCode.OK);
            server.HttpClient.GetAsync("http://local.test/test/action").Result.StatusCode.Should().Be(HttpStatusCode.OK);
            server.HttpClient.GetAsync("http://local.test/test/action").Result.StatusCode.Should().Be(HttpStatusCode.OK);
            var postContent = new StringContent(json);
            postContent.Headers.Add("Content-Length", json.Length.ToString());
            server.HttpClient.PostAsync("http://local.test/test/post", postContent);
        }
 public MetricInfo(string context, string metricName, MetricTags tags, TimerMetric timer, PerfCounterGauge perfCounter)
 {
     this.Context = context;
     this.MetricName = metricName;
     this.Tags = tags;
     this.Timer = timer;
     this.PerfCounter = perfCounter;
     this.Key = TagName(this.Context + this.MetricName, this.Tags);
 }
 private void LogTimer(IRequest request, MetricName metricName, TimerMetric metric, long timestamp)
 {
     LogGauge(request, metricName.Name + "." + TimerMetrics.FifteenMinuteRate.GetDatadogName(), metric.FifteenMinuteRate, timestamp);
     LogGauge(request, metricName.Name + "." + TimerMetrics.FiveMinuteRate.GetDatadogName(), metric.FiveMinuteRate, timestamp);
     LogGauge(request, metricName.Name + "." + TimerMetrics.OneMinuteRate.GetDatadogName(), metric.OneMinuteRate, timestamp);
     LogGauge(request, metricName.Name + "." + TimerMetrics.Max.GetDatadogName(), metric.Max, timestamp);
     LogGauge(request, metricName.Name + "." + TimerMetrics.Mean.GetDatadogName(), metric.Mean, timestamp);
     LogGauge(request, metricName.Name + "." + TimerMetrics.MeanRate.GetDatadogName(), metric.MeanRate, timestamp);
     LogGauge(request, metricName.Name + "." + TimerMetrics.Min.GetDatadogName(), metric.Min, timestamp);
     LogGauge(request, metricName.Name + "." + TimerMetrics.StdDev.GetDatadogName(), metric.StdDev, timestamp);
 }
 public TimerMetricTests()
 {
     _timer = new TimerMetric(new HistogramMetric(new UniformReservoir(Constants.ReservoirSampling.DefaultSampleSize)), new MeterMetric(_clock, new TestTaskScheduler(_clock)),
                              _clock);
 }
Exemple #29
0
        static void Main(string[] args)
        {
            var options = new Options();

            if (!Parser.Default.ParseArguments(args, options, (t, o) => { target = t; targetOptions = o as CommonOptions; }))
            {
                Console.WriteLine(new CommonOptions().GetUsage());
                Environment.Exit(CommandLine.Parser.DefaultExitCodeFail);
            }

            BenchmarkRunner.DefaultTotalSeconds = targetOptions.Seconds;
            BenchmarkRunner.DefaultMaxThreads   = targetOptions.MaxThreads;

            //Metric.Config.WithHttpEndpoint("http://localhost:1234/");

            switch (target)
            {
            case "noop":
                BenchmarkRunner.Run("Noop", () => { });
                break;

            case "counter":
                var counter = new CounterMetric();
                BenchmarkRunner.Run("Counter", () => counter.Increment());
                break;

            case "meter":
                var meter = new MeterMetric();
                BenchmarkRunner.Run("Meter", () => meter.Mark());
                break;

            case "histogram":
                var histogram = new HistogramMetric();
                BenchmarkRunner.Run("Histogram", () => histogram.Update(137));
                break;

            case "timer":
                var timer = new TimerMetric();
                BenchmarkRunner.Run("Timer", () => timer.Record(1, TimeUnit.Milliseconds));
                break;

            case "hdrtimer":
                var hdrTimer = new TimerMetric(new HdrHistogramReservoir());
                BenchmarkRunner.Run("HDR Timer", () => hdrTimer.Record(1, TimeUnit.Milliseconds));
                break;

            case "ewma":
                var ewma = EWMA.OneMinuteEWMA();
                BenchmarkRunner.Run("EWMA", () => ewma.Update(1));
                break;

            case "edr":
                var edr = new ExponentiallyDecayingReservoir();
                BenchmarkRunner.Run("EDR", () => edr.Update(1));
                break;

            case "hdr":
                var hdrReservoir = new HdrHistogramReservoir();
                BenchmarkRunner.Run("HDR Recorder", () => hdrReservoir.Update(1));
                break;

            case "uniform":
                var uniform = new UniformReservoir();
                BenchmarkRunner.Run("Uniform", () => uniform.Update(1));
                break;

            case "sliding":
                var sliding = new SlidingWindowReservoir();
                BenchmarkRunner.Run("Sliding", () => sliding.Update(1));
                break;

            case "timerimpact":
                var load = new WorkLoad();
                BenchmarkRunner.Run("WorkWithoutTimer", () => load.DoSomeWork(), iterationsChunk: 10);
                BenchmarkRunner.Run("WorkWithTimer", () => load.DoSomeWorkWithATimer(), iterationsChunk: 10);
                break;
            }
        }
 public TimerMetricTests()
 {
     this.scheduler = new TestScheduler(clock);
     this.timer     = new TimerMetric(SamplingType.FavourRecent, new MeterMetric(clock, scheduler), clock);
 }
Exemple #31
0
        private static void WriteTimer(TextWriter writer, TimerMetric timer)
        {
            WriteMetered(writer, timer);

            WriteDistributed(writer, timer);
        }
        protected void WriteTimer(StringBuilder sb, TimerMetric timer)
        {
            WriteMetered(sb, timer);

            var durationUnit = Abbreviate(timer.DurationUnit);

            var percentiles = timer.Percentiles(0.5, 0.75, 0.95, 0.98, 0.99, 0.999);

            sb.AppendFormat("               min = %{0:2}{1}\n", timer.Min, durationUnit);
            sb.AppendFormat("               max = %{0:2}{1}\n", timer.Max, durationUnit);
            sb.AppendFormat("              mean = %{0:2}{1}\n", timer.Mean, durationUnit);
            sb.AppendFormat("            stddev = %{0:2}{1}\n", timer.StdDev, durationUnit);
            sb.AppendFormat("            median = %{0:2}{1}\n", percentiles[0], durationUnit);
            sb.AppendFormat("              75%% <= %{0:2}{1}\n", percentiles[1], durationUnit);
            sb.AppendFormat("              95%% <= %{0:2}{1}\n", percentiles[2], durationUnit);
            sb.AppendFormat("              98%% <= %{0:2}{1}\n", percentiles[3], durationUnit);
            sb.AppendFormat("              99%% <= %{0:2}{1}\n", percentiles[4], durationUnit);
            sb.AppendFormat("            99.9%% <= %{0:2}{1}\n", percentiles[5], durationUnit);
        }
        private void WriteTimer(TimerMetric timer)
        {
            WriteMetered(timer);

            var durationUnit = Abbreviate(timer.DurationUnit);

            var percentiles = timer.Percentiles(0.5, 0.75, 0.95, 0.98, 0.99, 0.999);

            _out.Write("               min = %{0:2}{1}\n", timer.Min, durationUnit);
            _out.Write("               max = %{0:2}{1}\n", timer.Max, durationUnit);
            _out.Write("              mean = %{0:2}{1}\n", timer.Mean, durationUnit);
            _out.Write("            stddev = %{0:2}{1}\n", timer.StdDev, durationUnit);
            _out.Write("            median = %{0:2}{1}\n", percentiles[0], durationUnit);
            _out.Write("              75%% <= %{0:2}{1}\n", percentiles[1], durationUnit);
            _out.Write("              95%% <= %{0:2}{1}\n", percentiles[2], durationUnit);
            _out.Write("              98%% <= %{0:2}{1}\n", percentiles[3], durationUnit);
            _out.Write("              99%% <= %{0:2}{1}\n", percentiles[4], durationUnit);
            _out.Write("            99.9%% <= %{0:2}{1}\n", percentiles[5], durationUnit);
        }
        private MetricInfo RegisterMetric(PdhCounterPathElement pathElement, IDictionary<String, MetricInfo> existingMetrics)
        {
            string contextName = CleanName(pathElement.ObjectName);
            string metricName = CleanName(pathElement.CounterName);
            string instanceName = CleanName(pathElement.InstanceName);

            MetricTags tags = default(MetricTags);
            if (instanceName != null)
            {
                tags = "instance=" + instanceName;
            }
            string keyName = MetricInfo.TagName(contextName + metricName, tags);
            MetricInfo mInfo;
            if (existingMetrics.TryGetValue(keyName, out mInfo))
            {
                existingMetrics.Remove(keyName);
                return mInfo;
            }

            PerfCounterGauge pcGauge = new PerfCounterGauge(pathElement.ObjectName, pathElement.CounterName, pathElement.InstanceName);
            TimerMetric timer = null;
            PerformanceCounterType type = pcGauge.performanceCounter.CounterType;
            switch (type)
            {
                //these types of counters are not usable
                case PerformanceCounterType.AverageBase:
                case PerformanceCounterType.CounterMultiBase:
                case PerformanceCounterType.RawBase:
                case PerformanceCounterType.SampleBase:
                    _log.Error(String.Format("Don't know how to handle metric of type {0} for {1}", type.ToString(), metricName));
                    return null;

                //timers
                case PerformanceCounterType.AverageTimer32:
                case PerformanceCounterType.ElapsedTime:
                    timer = new TimerMetric(SamplingType.FavourRecent);
                    break;
            }
            mInfo = new MetricInfo(contextName, metricName, tags, timer, pcGauge);
            if (mInfo.Timer != null)
            {
                _timers[keyName] = mInfo;
            }
            return mInfo;
        }