github.com/klaytn/klaytn@v1.12.1/metrics/hybrid_timer.go (about)

     1  // Copyright 2021 The klaytn Authors
     2  // This file is part of the klaytn library.
     3  //
     4  // The klaytn library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The klaytn library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the klaytn library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package metrics
    18  
    19  import (
    20  	"sync"
    21  	"time"
    22  
    23  	"github.com/rcrowley/go-metrics"
    24  )
    25  
    26  const gaugeSuffix = "/maxgauge"
    27  
    28  var (
    29  	mu     sync.Mutex
    30  	gauges = make(map[string]metrics.Gauge)
    31  )
    32  
    33  // ResetMaxGauges sets the value of registered gauges to 0.
    34  func ResetMaxGauges() {
    35  	mu.Lock()
    36  	defer mu.Unlock()
    37  	for _, g := range gauges {
    38  		g.Update(0)
    39  	}
    40  }
    41  
    42  // registerHybridGauge registers the given metric under the given name.
    43  // It returns a DuplicateMetric if a metric by the given name is already registered.
    44  func registerHybridGauge(name string, g metrics.Gauge) {
    45  	mu.Lock()
    46  	defer mu.Unlock()
    47  
    48  	if _, exist := gauges[name]; exist {
    49  		return
    50  	}
    51  	gauges[name] = g
    52  }
    53  
    54  // HybridTimer holds both metrics.Meter and metrics.Gauge to track
    55  // meter-wise value and temporal maximum value during the certain period.
    56  type HybridTimer interface {
    57  	Update(d time.Duration)
    58  }
    59  
    60  type hybridTimer struct {
    61  	m metrics.Meter
    62  	g metrics.Gauge
    63  }
    64  
    65  // NewRegisteredHybridTimer constructs and registers a new HybridTimer.
    66  // `name` is used by meter and `name`+"/maxgauge" is used by gauge.
    67  func NewRegisteredHybridTimer(name string, r metrics.Registry) HybridTimer {
    68  	meter := metrics.NewRegisteredMeter(name, r)
    69  	gaugeName := name + gaugeSuffix
    70  
    71  	g := metrics.NewRegisteredGauge(gaugeName, r)
    72  	registerHybridGauge(gaugeName, g)
    73  	return &hybridTimer{m: meter, g: g}
    74  }
    75  
    76  // Update updates the value of meter and gauge.
    77  // The value of gauge is updated only if the current value
    78  // is greater than the current value.
    79  func (mg *hybridTimer) Update(d time.Duration) {
    80  	if mg.g.Value() < int64(d) {
    81  		mg.g.Update(int64(d))
    82  	}
    83  	mg.m.Mark(int64(d))
    84  }