/**
 * Copyright 2017 Pivotal Software, Inc.
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.micrometer.core.samples;

import cern.jet.random.Normal;
import cern.jet.random.engine.MersenneTwister64;
import cern.jet.random.engine.RandomEngine;
import io.micrometer.core.instrument.FunctionTimer;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import io.micrometer.core.samples.utils.SampleConfig;
import reactor.core.publisher.Flux;

import java.time.Duration;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class TimerSample {
    public static void main(String[] args) {
        MeterRegistry registry = SampleConfig.myMonitoringSystem();
        Timer timer = Timer.builder("timer")
                .publishPercentileHistogram()
                .publishPercentiles(0.5, 0.95, 0.99)
                .sla(Duration.ofMillis(275), Duration.ofMillis(300), Duration.ofMillis(500))
                .distributionStatisticExpiry(Duration.ofSeconds(10))
                .distributionStatisticBufferLength(3)
                .register(registry);

//        FunctionTimer.builder("ftimer", timer, Timer::count, t -> t.totalTime(TimeUnit.SECONDS), TimeUnit.SECONDS)
//                .register(registry);

        RandomEngine r = new MersenneTwister64(0);
        Normal incomingRequests = new Normal(0, 1, r);
        Normal duration = new Normal(250, 50, r);

        AtomicInteger latencyForThisSecond = new AtomicInteger(duration.nextInt());
        Flux.interval(Duration.ofSeconds(1))
                .doOnEach(d -> latencyForThisSecond.set(duration.nextInt()))
                .subscribe();

        // the potential for an "incoming request" every 10 ms
        Flux.interval(Duration.ofMillis(10))
                .doOnEach(d -> {
                    if (incomingRequests.nextDouble() + 0.4 > 0) {
                        // pretend the request took some amount of time, such that the time is
                        // distributed normally with a mean of 250ms
                        timer.record(latencyForThisSecond.get(), TimeUnit.MILLISECONDS);
                    }
                })
                .blockLast();
    }
}

@@ -913,24 +913,89 @@
 ment.Timer;%0A
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;%0A
 import io.mi
@@ -1187,16 +1187,63 @@
 Integer;
+%0Aimport java.util.concurrent.atomic.AtomicLong;
 %0A%0Apublic
@@ -1766,30 +1766,144 @@
 ter(
-r
+new SimpleMeterR
 egistry
+()
 );%0A%0A
-//
    
+     AtomicLong totalCount = new AtomicLong();%0A        AtomicLong totalTime = new AtomicLong();%0A
      
+   
 Func
@@ -1935,35 +1935,47 @@
 %22, t
-imer, Timer::count
+otalCount, t -%3E totalCount.get()
 , t -%3E 
-t.
 tota
@@ -1983,25 +1983,13 @@
 Time
-(TimeUnit.SECONDS
+.get(
 ), T
@@ -1996,16 +1996,21 @@
 imeUnit.
+MILLI
 SECONDS)
@@ -2010,18 +2010,16 @@
 ECONDS)%0A
-//
         
@@ -2842,21 +2842,22 @@
     
-timer.record(
+int latency = 
 late
@@ -2878,39 +2878,193 @@
 nd.get()
-, TimeUnit.MILLISECONDS
+;%0A                        timer.record(latency, TimeUnit.MILLISECONDS);%0A                        totalTime.addAndGet(latency);%0A                        totalCount.incrementAndGet(
 );%0A     

Fix TimerSample for step-based registries