github.com/Jeffail/benthos/v3@v3.65.0/lib/metrics/statsd_legacy.go (about)

     1  package metrics
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/Jeffail/benthos/v3/lib/log"
     8  	"github.com/quipo/statsd"
     9  )
    10  
    11  //------------------------------------------------------------------------------
    12  
    13  type wrappedLogger struct {
    14  	m log.Modular
    15  }
    16  
    17  func (w *wrappedLogger) Println(v ...interface{}) {
    18  	w.m.Warnf(fmt.Sprintln(v...))
    19  }
    20  
    21  //------------------------------------------------------------------------------
    22  
    23  // StatsdLegacyStat is a representation of a single metric stat. Interactions with
    24  // this stat are thread safe.
    25  type StatsdLegacyStat struct {
    26  	path string
    27  	s    statsd.Statsd
    28  }
    29  
    30  // Incr increments a metric by an amount.
    31  func (s *StatsdLegacyStat) Incr(count int64) error {
    32  	s.s.Incr(s.path, count)
    33  	return nil
    34  }
    35  
    36  // Decr decrements a metric by an amount.
    37  func (s *StatsdLegacyStat) Decr(count int64) error {
    38  	s.s.Decr(s.path, count)
    39  	return nil
    40  }
    41  
    42  // Timing sets a timing metric.
    43  func (s *StatsdLegacyStat) Timing(delta int64) error {
    44  	s.s.Timing(s.path, delta)
    45  	return nil
    46  }
    47  
    48  // Set sets a gauge metric.
    49  func (s *StatsdLegacyStat) Set(value int64) error {
    50  	s.s.Gauge(s.path, value)
    51  	return nil
    52  }
    53  
    54  //------------------------------------------------------------------------------
    55  
    56  // StatsdLegacy is a stats object with capability to hold internal stats as a JSON
    57  // endpoint.
    58  type StatsdLegacy struct {
    59  	config      Config
    60  	s           statsd.Statsd
    61  	log         log.Modular
    62  	pathMapping *pathMapping
    63  }
    64  
    65  // NewStatsdLegacy creates and returns a new StatsdLegacy object.
    66  func NewStatsdLegacy(config Config, opts ...func(Type)) (Type, error) {
    67  	flushPeriod, err := time.ParseDuration(config.Statsd.FlushPeriod)
    68  	if err != nil {
    69  		return nil, fmt.Errorf("failed to parse flush period: %s", err)
    70  	}
    71  	s := &StatsdLegacy{
    72  		config: config,
    73  		log:    log.Noop(),
    74  	}
    75  	for _, opt := range opts {
    76  		opt(s)
    77  	}
    78  
    79  	if s.pathMapping, err = newPathMapping(config.Statsd.PathMapping, s.log); err != nil {
    80  		return nil, fmt.Errorf("failed to init path mapping: %v", err)
    81  	}
    82  
    83  	if config.Statsd.Network == "tcp" {
    84  		s.log.Warnf(
    85  			"Network set to 'tcp', falling back to legacy statsd client. The " +
    86  				"network field is due to be removed in the next major release, " +
    87  				" if you are relying on this field please raise an issue at: " +
    88  				"https://github.com/Jeffail/benthos/issues\n",
    89  		)
    90  	} else {
    91  		s.log.Warnf(
    92  			"Falling back to legacy statsd client. To use the new client set " +
    93  				"the 'tag_format' field to 'none', 'datadog' or 'influxdb'. The " +
    94  				"network field is due to be removed in the next major release, " +
    95  				"if you are relying on this field please raise an issue at: " +
    96  				"https://github.com/Jeffail/benthos/issues\n",
    97  		)
    98  	}
    99  
   100  	if config.Statsd.TagFormat != TagFormatNone && config.Statsd.TagFormat != TagFormatLegacy {
   101  		return nil, fmt.Errorf("tag format '%v' is not supported when using 'tcp' network traffic", config.Statsd.TagFormat)
   102  	}
   103  
   104  	prefix := config.Statsd.Prefix
   105  	if len(prefix) > 0 && prefix[len(prefix)-1] != '.' {
   106  		prefix += "."
   107  	}
   108  
   109  	statsdclient := statsd.NewStatsdBuffer(
   110  		flushPeriod,
   111  		statsd.NewStatsdClient(config.Statsd.Address, prefix),
   112  	)
   113  	statsdclient.Logger = &wrappedLogger{m: s.log}
   114  	if config.Statsd.Network == "udp" {
   115  		if err := statsdclient.CreateSocket(); err != nil {
   116  			return nil, err
   117  		}
   118  	} else {
   119  		if err := statsdclient.CreateTCPSocket(); err != nil {
   120  			return nil, err
   121  		}
   122  	}
   123  	s.s = statsdclient
   124  	return s, nil
   125  }
   126  
   127  //------------------------------------------------------------------------------
   128  
   129  // GetCounter returns a stat counter object for a path.
   130  func (h *StatsdLegacy) GetCounter(path string) StatCounter {
   131  	if path = h.pathMapping.mapPathNoTags(path); path == "" {
   132  		return DudStat{}
   133  	}
   134  	return &StatsdLegacyStat{
   135  		path: path,
   136  		s:    h.s,
   137  	}
   138  }
   139  
   140  // GetCounterVec returns a stat counter object for a path with the labels
   141  // discarded.
   142  func (h *StatsdLegacy) GetCounterVec(path string, n []string) StatCounterVec {
   143  	path = h.pathMapping.mapPathNoTags(path)
   144  	return fakeCounterVec(func([]string) StatCounter {
   145  		if path == "" {
   146  			return DudStat{}
   147  		}
   148  		return &StatsdLegacyStat{
   149  			path: path,
   150  			s:    h.s,
   151  		}
   152  	})
   153  }
   154  
   155  // GetTimer returns a stat timer object for a path.
   156  func (h *StatsdLegacy) GetTimer(path string) StatTimer {
   157  	if path = h.pathMapping.mapPathNoTags(path); path == "" {
   158  		return DudStat{}
   159  	}
   160  	return &StatsdLegacyStat{
   161  		path: path,
   162  		s:    h.s,
   163  	}
   164  }
   165  
   166  // GetTimerVec returns a stat timer object for a path with the labels
   167  // discarded.
   168  func (h *StatsdLegacy) GetTimerVec(path string, n []string) StatTimerVec {
   169  	path = h.pathMapping.mapPathNoTags(path)
   170  	return fakeTimerVec(func([]string) StatTimer {
   171  		if path == "" {
   172  			return DudStat{}
   173  		}
   174  		return &StatsdLegacyStat{
   175  			path: path,
   176  			s:    h.s,
   177  		}
   178  	})
   179  }
   180  
   181  // GetGauge returns a stat gauge object for a path.
   182  func (h *StatsdLegacy) GetGauge(path string) StatGauge {
   183  	if path = h.pathMapping.mapPathNoTags(path); path == "" {
   184  		return DudStat{}
   185  	}
   186  	return &StatsdLegacyStat{
   187  		path: path,
   188  		s:    h.s,
   189  	}
   190  }
   191  
   192  // GetGaugeVec returns a stat timer object for a path with the labels
   193  // discarded.
   194  func (h *StatsdLegacy) GetGaugeVec(path string, n []string) StatGaugeVec {
   195  	path = h.pathMapping.mapPathNoTags(path)
   196  	return fakeGaugeVec(func([]string) StatGauge {
   197  		if path == "" {
   198  			return DudStat{}
   199  		}
   200  		return &StatsdLegacyStat{
   201  			path: path,
   202  			s:    h.s,
   203  		}
   204  	})
   205  }
   206  
   207  // SetLogger sets the logger used to print connection errors.
   208  func (h *StatsdLegacy) SetLogger(log log.Modular) {
   209  	h.log = log
   210  }
   211  
   212  // Close stops the StatsdLegacy object from aggregating metrics and cleans up
   213  // resources.
   214  func (h *StatsdLegacy) Close() error {
   215  	h.s.Close()
   216  	return nil
   217  }
   218  
   219  //------------------------------------------------------------------------------