An average can look comfortable while some requests are slow. Keep a distribution summary alongside its valid sample count and sum.
This exercise builds a small fixed-bucket cumulative histogram. It teaches boundary/denominator semantics; it is not a replacement for a maintained metrics client. Current Prometheus guidance prefers native histograms for real deployments.
The finite upper bounds are 10, 50, 100, 500, 1000 and 5000 milliseconds. The final bucket is +Inf. Equality is included: a 50 ms value belongs in <=50.
Validate before mutation. A negative duration is not a meaningful observation; integer overflow must not silently wrap the count or sum. Missing timing is handled by skipping Observe, not by passing zero.
package main
import ("fmt")
func main(){
bounds:=[]int64{10,50,100};value:=int64(50);for _,bound:=range bounds{fmt.Println(bound,value<=bound)}
}For the mean, combine total sums and total counts before dividing. Do not average group averages as though every group had equal traffic.
P95Bound finds the bucket reaching ceil(0.95 × count). It reports a finite upper bound, not an exact quantile. If the selected rank lies beyond 5000 ms, the result is unbounded at this resolution; an empty histogram is a different state. Neither should become a fabricated zero or a finite claim.
Snapshots copy the fixed arrays and sort method/route rows. The local replay uses deterministic durations to make these states inspectable; those values are scenario inputs, not a performance result for the host.
package main
import ("fmt")
func main(){
fast,slow:=18.0*10,2.0*1000;fmt.Println((fast+slow)/20,1000)
}Complete Observe and test zero, exact boundaries, above-last-bound, empty state and overflow. Describe p95 as a bucket bound in every output.
Next we connect emitted log events to the corresponding counter series and choose an investigation exemplar.