github.com/uber-go/tally/v4@v4.1.17/multi/reporter.go (about)

     1  // Copyright (c) 2021 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package multi
    22  
    23  import (
    24  	"time"
    25  
    26  	tally "github.com/uber-go/tally/v4"
    27  )
    28  
    29  type multi struct {
    30  	multiBaseReporters multiBaseReporters
    31  	reporters          []tally.StatsReporter
    32  }
    33  
    34  // NewMultiReporter creates a new multi tally.StatsReporter.
    35  func NewMultiReporter(
    36  	r ...tally.StatsReporter,
    37  ) tally.StatsReporter {
    38  	var baseReporters multiBaseReporters
    39  	for _, r := range r {
    40  		baseReporters = append(baseReporters, r)
    41  	}
    42  	return &multi{
    43  		multiBaseReporters: baseReporters,
    44  		reporters:          r,
    45  	}
    46  }
    47  
    48  func (r *multi) ReportCounter(
    49  	name string,
    50  	tags map[string]string,
    51  	value int64,
    52  ) {
    53  	for _, r := range r.reporters {
    54  		r.ReportCounter(name, tags, value)
    55  	}
    56  }
    57  
    58  func (r *multi) ReportGauge(
    59  	name string,
    60  	tags map[string]string,
    61  	value float64,
    62  ) {
    63  	for _, r := range r.reporters {
    64  		r.ReportGauge(name, tags, value)
    65  	}
    66  }
    67  
    68  func (r *multi) ReportTimer(
    69  	name string,
    70  	tags map[string]string,
    71  	interval time.Duration,
    72  ) {
    73  	for _, r := range r.reporters {
    74  		r.ReportTimer(name, tags, interval)
    75  	}
    76  }
    77  
    78  func (r *multi) ReportHistogramValueSamples(
    79  	name string,
    80  	tags map[string]string,
    81  	buckets tally.Buckets,
    82  	bucketLowerBound,
    83  	bucketUpperBound float64,
    84  	samples int64,
    85  ) {
    86  	for _, r := range r.reporters {
    87  		r.ReportHistogramValueSamples(name, tags, buckets,
    88  			bucketLowerBound, bucketUpperBound, samples)
    89  	}
    90  }
    91  
    92  func (r *multi) ReportHistogramDurationSamples(
    93  	name string,
    94  	tags map[string]string,
    95  	buckets tally.Buckets,
    96  	bucketLowerBound,
    97  	bucketUpperBound time.Duration,
    98  	samples int64,
    99  ) {
   100  	for _, r := range r.reporters {
   101  		r.ReportHistogramDurationSamples(name, tags, buckets,
   102  			bucketLowerBound, bucketUpperBound, samples)
   103  	}
   104  }
   105  
   106  func (r *multi) Capabilities() tally.Capabilities {
   107  	return r.multiBaseReporters.Capabilities()
   108  }
   109  
   110  func (r *multi) Flush() {
   111  	r.multiBaseReporters.Flush()
   112  }
   113  
   114  type multiCached struct {
   115  	multiBaseReporters multiBaseReporters
   116  	reporters          []tally.CachedStatsReporter
   117  }
   118  
   119  // NewMultiCachedReporter creates a new multi tally.CachedStatsReporter.
   120  func NewMultiCachedReporter(
   121  	r ...tally.CachedStatsReporter,
   122  ) tally.CachedStatsReporter {
   123  	var baseReporters multiBaseReporters
   124  	for _, r := range r {
   125  		baseReporters = append(baseReporters, r)
   126  	}
   127  	return &multiCached{
   128  		multiBaseReporters: baseReporters,
   129  		reporters:          r,
   130  	}
   131  }
   132  
   133  func (r *multiCached) AllocateCounter(
   134  	name string,
   135  	tags map[string]string,
   136  ) tally.CachedCount {
   137  	metrics := make([]tally.CachedCount, 0, len(r.reporters))
   138  	for _, r := range r.reporters {
   139  		metrics = append(metrics, r.AllocateCounter(name, tags))
   140  	}
   141  	return multiMetric{counters: metrics}
   142  }
   143  
   144  func (r *multiCached) AllocateGauge(
   145  	name string,
   146  	tags map[string]string,
   147  ) tally.CachedGauge {
   148  	metrics := make([]tally.CachedGauge, 0, len(r.reporters))
   149  	for _, r := range r.reporters {
   150  		metrics = append(metrics, r.AllocateGauge(name, tags))
   151  	}
   152  	return multiMetric{gauges: metrics}
   153  }
   154  
   155  func (r *multiCached) AllocateTimer(
   156  	name string,
   157  	tags map[string]string,
   158  ) tally.CachedTimer {
   159  	metrics := make([]tally.CachedTimer, 0, len(r.reporters))
   160  	for _, r := range r.reporters {
   161  		metrics = append(metrics, r.AllocateTimer(name, tags))
   162  	}
   163  	return multiMetric{timers: metrics}
   164  }
   165  
   166  func (r *multiCached) AllocateHistogram(
   167  	name string,
   168  	tags map[string]string,
   169  	buckets tally.Buckets,
   170  ) tally.CachedHistogram {
   171  	metrics := make([]tally.CachedHistogram, 0, len(r.reporters))
   172  	for _, r := range r.reporters {
   173  		metrics = append(metrics, r.AllocateHistogram(name, tags, buckets))
   174  	}
   175  	return multiMetric{histograms: metrics}
   176  }
   177  
   178  func (r *multiCached) Capabilities() tally.Capabilities {
   179  	return r.multiBaseReporters.Capabilities()
   180  }
   181  
   182  func (r *multiCached) Flush() {
   183  	r.multiBaseReporters.Flush()
   184  }
   185  
   186  type multiMetric struct {
   187  	counters   []tally.CachedCount
   188  	gauges     []tally.CachedGauge
   189  	timers     []tally.CachedTimer
   190  	histograms []tally.CachedHistogram
   191  }
   192  
   193  func (m multiMetric) ReportCount(value int64) {
   194  	for _, m := range m.counters {
   195  		m.ReportCount(value)
   196  	}
   197  }
   198  
   199  func (m multiMetric) ReportGauge(value float64) {
   200  	for _, m := range m.gauges {
   201  		m.ReportGauge(value)
   202  	}
   203  }
   204  
   205  func (m multiMetric) ReportTimer(interval time.Duration) {
   206  	for _, m := range m.timers {
   207  		m.ReportTimer(interval)
   208  	}
   209  }
   210  
   211  func (m multiMetric) ValueBucket(
   212  	bucketLowerBound, bucketUpperBound float64,
   213  ) tally.CachedHistogramBucket {
   214  	var multi []tally.CachedHistogramBucket
   215  	for _, m := range m.histograms {
   216  		multi = append(multi,
   217  			m.ValueBucket(bucketLowerBound, bucketUpperBound))
   218  	}
   219  	return multiHistogramBucket{multi}
   220  }
   221  
   222  func (m multiMetric) DurationBucket(
   223  	bucketLowerBound, bucketUpperBound time.Duration,
   224  ) tally.CachedHistogramBucket {
   225  	var multi []tally.CachedHistogramBucket
   226  	for _, m := range m.histograms {
   227  		multi = append(multi,
   228  			m.DurationBucket(bucketLowerBound, bucketUpperBound))
   229  	}
   230  	return multiHistogramBucket{multi}
   231  }
   232  
   233  type multiHistogramBucket struct {
   234  	multi []tally.CachedHistogramBucket
   235  }
   236  
   237  func (m multiHistogramBucket) ReportSamples(value int64) {
   238  	for _, m := range m.multi {
   239  		m.ReportSamples(value)
   240  	}
   241  }
   242  
   243  type multiBaseReporters []tally.BaseStatsReporter
   244  
   245  func (r multiBaseReporters) Capabilities() tally.Capabilities {
   246  	c := &capabilities{reporting: true, tagging: true}
   247  	for _, r := range r {
   248  		c.reporting = c.reporting && r.Capabilities().Reporting()
   249  		c.tagging = c.tagging && r.Capabilities().Tagging()
   250  	}
   251  	return c
   252  }
   253  
   254  func (r multiBaseReporters) Flush() {
   255  	for _, r := range r {
   256  		r.Flush()
   257  	}
   258  }
   259  
   260  type capabilities struct {
   261  	reporting bool
   262  	tagging   bool
   263  }
   264  
   265  func (c *capabilities) Reporting() bool {
   266  	return c.reporting
   267  }
   268  
   269  func (c *capabilities) Tagging() bool {
   270  	return c.tagging
   271  }