github.com/influxdata/telegraf@v1.30.3/testutil/accumulator.go (about)

     1  package testutil
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"reflect"
     7  	"sync"
     8  	"sync/atomic"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/stretchr/testify/require"
    13  
    14  	"github.com/influxdata/telegraf"
    15  	"github.com/influxdata/telegraf/metric"
    16  )
    17  
    18  // Metric defines a single point measurement
    19  type Metric struct {
    20  	Measurement string
    21  	Tags        map[string]string
    22  	Fields      map[string]interface{}
    23  	Time        time.Time
    24  	Type        telegraf.ValueType
    25  }
    26  
    27  func (p *Metric) String() string {
    28  	return fmt.Sprintf("%s %v %v", p.Measurement, p.Tags, p.Fields)
    29  }
    30  
    31  // Accumulator defines a mocked out accumulator
    32  type Accumulator struct {
    33  	nMetrics    uint64 // Needs to be first to avoid unaligned atomic operations on 32-bit archs
    34  	Metrics     []*Metric
    35  	accumulated []telegraf.Metric
    36  	Discard     bool
    37  	Errors      []error
    38  	debug       bool
    39  	deliverChan chan telegraf.DeliveryInfo
    40  	delivered   []telegraf.DeliveryInfo
    41  
    42  	TimeFunc func() time.Time
    43  
    44  	sync.Mutex
    45  	*sync.Cond
    46  }
    47  
    48  func (a *Accumulator) NMetrics() uint64 {
    49  	return atomic.LoadUint64(&a.nMetrics)
    50  }
    51  
    52  func (a *Accumulator) NDelivered() int {
    53  	a.Lock()
    54  	defer a.Unlock()
    55  	return len(a.delivered)
    56  }
    57  
    58  // GetTelegrafMetrics returns all the metrics collected by the accumulator
    59  // If you are getting race conditions here then you are not waiting for all of your metrics to arrive: see Wait()
    60  func (a *Accumulator) GetTelegrafMetrics() []telegraf.Metric {
    61  	a.Lock()
    62  	defer a.Unlock()
    63  	metrics := make([]telegraf.Metric, 0, len(a.accumulated))
    64  	metrics = append(metrics, a.accumulated...)
    65  	return metrics
    66  }
    67  
    68  func (a *Accumulator) GetDeliveries() []telegraf.DeliveryInfo {
    69  	a.Lock()
    70  	defer a.Unlock()
    71  	info := make([]telegraf.DeliveryInfo, 0, len(a.delivered))
    72  	info = append(info, a.delivered...)
    73  	return info
    74  }
    75  
    76  func (a *Accumulator) FirstError() error {
    77  	if len(a.Errors) == 0 {
    78  		return nil
    79  	}
    80  	return a.Errors[0]
    81  }
    82  
    83  func (a *Accumulator) ClearMetrics() {
    84  	a.Lock()
    85  	defer a.Unlock()
    86  	atomic.StoreUint64(&a.nMetrics, 0)
    87  	a.Metrics = make([]*Metric, 0)
    88  	a.accumulated = make([]telegraf.Metric, 0)
    89  }
    90  
    91  func (a *Accumulator) addMeasurement(
    92  	measurement string,
    93  	tags map[string]string,
    94  	fields map[string]interface{},
    95  	tp telegraf.ValueType,
    96  	timestamp ...time.Time,
    97  ) {
    98  	a.Lock()
    99  	defer a.Unlock()
   100  	atomic.AddUint64(&a.nMetrics, 1)
   101  	if a.Cond != nil {
   102  		a.Cond.Broadcast()
   103  	}
   104  	if a.Discard {
   105  		return
   106  	}
   107  
   108  	if len(fields) == 0 {
   109  		return
   110  	}
   111  
   112  	tagsCopy := map[string]string{}
   113  	for k, v := range tags {
   114  		tagsCopy[k] = v
   115  	}
   116  
   117  	fieldsCopy := map[string]interface{}{}
   118  	for k, v := range fields {
   119  		fieldsCopy[k] = v
   120  	}
   121  
   122  	var t time.Time
   123  	if len(timestamp) > 0 {
   124  		t = timestamp[0]
   125  	} else {
   126  		if a.TimeFunc == nil {
   127  			t = time.Now()
   128  		} else {
   129  			t = a.TimeFunc()
   130  		}
   131  	}
   132  
   133  	if a.debug {
   134  		pretty, _ := json.MarshalIndent(fields, "", "  ")
   135  		prettyTags, _ := json.MarshalIndent(tags, "", "  ")
   136  		msg := fmt.Sprintf("Adding Measurement [%s]\nFields:%s\nTags:%s\n",
   137  			measurement, string(pretty), string(prettyTags))
   138  		fmt.Print(msg)
   139  	}
   140  
   141  	m := &Metric{
   142  		Measurement: measurement,
   143  		Fields:      fieldsCopy,
   144  		Tags:        tagsCopy,
   145  		Time:        t,
   146  		Type:        tp,
   147  	}
   148  
   149  	a.Metrics = append(a.Metrics, m)
   150  	a.accumulated = append(a.accumulated, FromTestMetric(m))
   151  }
   152  
   153  // AddFields adds a measurement point with a specified timestamp.
   154  func (a *Accumulator) AddFields(
   155  	measurement string,
   156  	fields map[string]interface{},
   157  	tags map[string]string,
   158  	timestamp ...time.Time,
   159  ) {
   160  	a.addMeasurement(measurement, tags, fields, telegraf.Untyped, timestamp...)
   161  }
   162  
   163  func (a *Accumulator) AddCounter(
   164  	measurement string,
   165  	fields map[string]interface{},
   166  	tags map[string]string,
   167  	timestamp ...time.Time,
   168  ) {
   169  	a.addMeasurement(measurement, tags, fields, telegraf.Counter, timestamp...)
   170  }
   171  
   172  func (a *Accumulator) AddGauge(
   173  	measurement string,
   174  	fields map[string]interface{},
   175  	tags map[string]string,
   176  	timestamp ...time.Time,
   177  ) {
   178  	a.addMeasurement(measurement, tags, fields, telegraf.Gauge, timestamp...)
   179  }
   180  
   181  func (a *Accumulator) AddMetrics(metrics []telegraf.Metric) {
   182  	for _, m := range metrics {
   183  		a.AddMetric(m)
   184  	}
   185  }
   186  
   187  func (a *Accumulator) AddSummary(
   188  	measurement string,
   189  	fields map[string]interface{},
   190  	tags map[string]string,
   191  	timestamp ...time.Time,
   192  ) {
   193  	a.addMeasurement(measurement, tags, fields, telegraf.Summary, timestamp...)
   194  }
   195  
   196  func (a *Accumulator) AddHistogram(
   197  	measurement string,
   198  	fields map[string]interface{},
   199  	tags map[string]string,
   200  	timestamp ...time.Time,
   201  ) {
   202  	a.addMeasurement(measurement, tags, fields, telegraf.Histogram, timestamp...)
   203  }
   204  
   205  func (a *Accumulator) AddMetric(m telegraf.Metric) {
   206  	a.Lock()
   207  	defer a.Unlock()
   208  	atomic.AddUint64(&a.nMetrics, 1)
   209  	if a.Cond != nil {
   210  		a.Cond.Broadcast()
   211  	}
   212  	if a.Discard {
   213  		return
   214  	}
   215  
   216  	// Drop metrics without fields
   217  	if len(m.FieldList()) == 0 {
   218  		return
   219  	}
   220  
   221  	a.Metrics = append(a.Metrics, ToTestMetric(m))
   222  	a.accumulated = append(a.accumulated, m)
   223  }
   224  
   225  func (a *Accumulator) WithTracking(maxTracked int) telegraf.TrackingAccumulator {
   226  	a.deliverChan = make(chan telegraf.DeliveryInfo, maxTracked)
   227  	a.delivered = make([]telegraf.DeliveryInfo, 0, maxTracked)
   228  	return a
   229  }
   230  
   231  func (a *Accumulator) AddTrackingMetric(m telegraf.Metric) telegraf.TrackingID {
   232  	dm, id := metric.WithTracking(m, a.onDelivery)
   233  	a.AddMetric(dm)
   234  	return id
   235  }
   236  
   237  func (a *Accumulator) AddTrackingMetricGroup(group []telegraf.Metric) telegraf.TrackingID {
   238  	db, id := metric.WithGroupTracking(group, a.onDelivery)
   239  	for _, m := range db {
   240  		a.AddMetric(m)
   241  	}
   242  	return id
   243  }
   244  
   245  func (a *Accumulator) onDelivery(info telegraf.DeliveryInfo) {
   246  	select {
   247  	case a.deliverChan <- info:
   248  	default:
   249  		// This is a programming error in the input.  More items were sent for
   250  		// tracking than space requested.
   251  		panic("channel is full")
   252  	}
   253  }
   254  
   255  func (a *Accumulator) Delivered() <-chan telegraf.DeliveryInfo {
   256  	return a.deliverChan
   257  }
   258  
   259  // AddError appends the given error to Accumulator.Errors.
   260  func (a *Accumulator) AddError(err error) {
   261  	if err == nil {
   262  		return
   263  	}
   264  	a.Lock()
   265  	a.Errors = append(a.Errors, err)
   266  	if a.Cond != nil {
   267  		a.Cond.Broadcast()
   268  	}
   269  	a.Unlock()
   270  }
   271  
   272  func (a *Accumulator) SetPrecision(_ time.Duration) {
   273  }
   274  
   275  func (a *Accumulator) DisablePrecision() {
   276  }
   277  
   278  func (a *Accumulator) Debug() bool {
   279  	// stub for implementing Accumulator interface.
   280  	return a.debug
   281  }
   282  
   283  func (a *Accumulator) SetDebug(debug bool) {
   284  	// stub for implementing Accumulator interface.
   285  	a.debug = debug
   286  }
   287  
   288  // Get gets the specified measurement point from the accumulator
   289  func (a *Accumulator) Get(measurement string) (*Metric, bool) {
   290  	for _, p := range a.Metrics {
   291  		if p.Measurement == measurement {
   292  			return p, true
   293  		}
   294  	}
   295  
   296  	return nil, false
   297  }
   298  
   299  func (a *Accumulator) HasTag(measurement string, key string) bool {
   300  	for _, p := range a.Metrics {
   301  		if p.Measurement == measurement {
   302  			_, ok := p.Tags[key]
   303  			return ok
   304  		}
   305  	}
   306  	return false
   307  }
   308  
   309  func (a *Accumulator) TagSetValue(measurement string, key string) string {
   310  	for _, p := range a.Metrics {
   311  		if p.Measurement == measurement {
   312  			v, ok := p.Tags[key]
   313  			if ok {
   314  				return v
   315  			}
   316  		}
   317  	}
   318  	return ""
   319  }
   320  
   321  func (a *Accumulator) TagValue(measurement string, key string) string {
   322  	for _, p := range a.Metrics {
   323  		if p.Measurement == measurement {
   324  			v, ok := p.Tags[key]
   325  			if !ok {
   326  				return ""
   327  			}
   328  			return v
   329  		}
   330  	}
   331  	return ""
   332  }
   333  
   334  // GatherError calls the given Gather function and returns the first error found.
   335  func (a *Accumulator) GatherError(gf func(telegraf.Accumulator) error) error {
   336  	if err := gf(a); err != nil {
   337  		return err
   338  	}
   339  	if len(a.Errors) > 0 {
   340  		return a.Errors[0]
   341  	}
   342  	return nil
   343  }
   344  
   345  // NFields returns the total number of fields in the accumulator, across all
   346  // measurements
   347  func (a *Accumulator) NFields() int {
   348  	a.Lock()
   349  	defer a.Unlock()
   350  	counter := 0
   351  	for _, pt := range a.Metrics {
   352  		for range pt.Fields {
   353  			counter++
   354  		}
   355  	}
   356  	return counter
   357  }
   358  
   359  // Wait waits for the given number of metrics to be added to the accumulator.
   360  func (a *Accumulator) Wait(n int) {
   361  	a.Lock()
   362  	defer a.Unlock()
   363  	if a.Cond == nil {
   364  		a.Cond = sync.NewCond(&a.Mutex)
   365  	}
   366  	for int(a.NMetrics()) < n {
   367  		a.Cond.Wait()
   368  	}
   369  }
   370  
   371  // WaitError waits for the given number of errors to be added to the accumulator.
   372  func (a *Accumulator) WaitError(n int) {
   373  	a.Lock()
   374  	if a.Cond == nil {
   375  		a.Cond = sync.NewCond(&a.Mutex)
   376  	}
   377  	for len(a.Errors) < n {
   378  		a.Cond.Wait()
   379  	}
   380  	a.Unlock()
   381  }
   382  
   383  func (a *Accumulator) AssertContainsTaggedFields(
   384  	t *testing.T,
   385  	measurement string,
   386  	fields map[string]interface{},
   387  	tags map[string]string,
   388  ) {
   389  	a.Lock()
   390  	defer a.Unlock()
   391  	for _, p := range a.Metrics {
   392  		if !reflect.DeepEqual(tags, p.Tags) {
   393  			continue
   394  		}
   395  
   396  		if p.Measurement == measurement && reflect.DeepEqual(fields, p.Fields) {
   397  			return
   398  		}
   399  	}
   400  	// We've failed. spit out some debug logging
   401  	for _, p := range a.Metrics {
   402  		if p.Measurement == measurement {
   403  			t.Log("measurement", p.Measurement, "tags", p.Tags, "fields", p.Fields)
   404  		}
   405  	}
   406  	msg := fmt.Sprintf("unknown measurement %q with tags %v", measurement, tags)
   407  	require.Fail(t, msg)
   408  }
   409  
   410  func (a *Accumulator) AssertDoesNotContainsTaggedFields(
   411  	t *testing.T,
   412  	measurement string,
   413  	fields map[string]interface{},
   414  	tags map[string]string,
   415  ) {
   416  	a.Lock()
   417  	defer a.Unlock()
   418  	for _, p := range a.Metrics {
   419  		if !reflect.DeepEqual(tags, p.Tags) {
   420  			continue
   421  		}
   422  
   423  		if p.Measurement == measurement && reflect.DeepEqual(fields, p.Fields) {
   424  			msg := fmt.Sprintf(
   425  				"found measurement %s with tagged fields (tags %v) which should not be there",
   426  				measurement, tags)
   427  			require.Fail(t, msg)
   428  		}
   429  	}
   430  }
   431  func (a *Accumulator) AssertContainsFields(
   432  	t *testing.T,
   433  	measurement string,
   434  	fields map[string]interface{},
   435  ) {
   436  	a.Lock()
   437  	defer a.Unlock()
   438  	for _, p := range a.Metrics {
   439  		if p.Measurement == measurement {
   440  			require.Equal(t, fields, p.Fields)
   441  			return
   442  		}
   443  	}
   444  	msg := fmt.Sprintf("unknown measurement %q", measurement)
   445  	require.Fail(t, msg)
   446  }
   447  
   448  func (a *Accumulator) HasPoint(
   449  	measurement string,
   450  	tags map[string]string,
   451  	fieldKey string,
   452  	fieldValue interface{},
   453  ) bool {
   454  	a.Lock()
   455  	defer a.Unlock()
   456  	for _, p := range a.Metrics {
   457  		if p.Measurement != measurement {
   458  			continue
   459  		}
   460  
   461  		if !reflect.DeepEqual(tags, p.Tags) {
   462  			continue
   463  		}
   464  
   465  		v, ok := p.Fields[fieldKey]
   466  		if ok && reflect.DeepEqual(v, fieldValue) {
   467  			return true
   468  		}
   469  	}
   470  	return false
   471  }
   472  
   473  func (a *Accumulator) AssertDoesNotContainMeasurement(t *testing.T, measurement string) {
   474  	a.Lock()
   475  	defer a.Unlock()
   476  	for _, p := range a.Metrics {
   477  		if p.Measurement == measurement {
   478  			msg := "found unexpected measurement " + measurement
   479  			require.Fail(t, msg)
   480  		}
   481  	}
   482  }
   483  
   484  // HasTimestamp returns true if the measurement has a matching Time value
   485  func (a *Accumulator) HasTimestamp(measurement string, timestamp time.Time) bool {
   486  	a.Lock()
   487  	defer a.Unlock()
   488  	for _, p := range a.Metrics {
   489  		if p.Measurement == measurement {
   490  			return timestamp.Equal(p.Time)
   491  		}
   492  	}
   493  
   494  	return false
   495  }
   496  
   497  // HasField returns true if the given measurement has a field with the given
   498  // name
   499  func (a *Accumulator) HasField(measurement string, field string) bool {
   500  	a.Lock()
   501  	defer a.Unlock()
   502  	for _, p := range a.Metrics {
   503  		if p.Measurement == measurement {
   504  			if _, ok := p.Fields[field]; ok {
   505  				return true
   506  			}
   507  		}
   508  	}
   509  
   510  	return false
   511  }
   512  
   513  // HasIntField returns true if the measurement has an Int value
   514  func (a *Accumulator) HasIntField(measurement string, field string) bool {
   515  	a.Lock()
   516  	defer a.Unlock()
   517  	for _, p := range a.Metrics {
   518  		if p.Measurement == measurement {
   519  			for fieldname, value := range p.Fields {
   520  				if fieldname == field {
   521  					_, ok := value.(int)
   522  					return ok
   523  				}
   524  			}
   525  		}
   526  	}
   527  
   528  	return false
   529  }
   530  
   531  // HasInt64Field returns true if the measurement has an Int64 value
   532  func (a *Accumulator) HasInt64Field(measurement string, field string) bool {
   533  	a.Lock()
   534  	defer a.Unlock()
   535  	for _, p := range a.Metrics {
   536  		if p.Measurement == measurement {
   537  			for fieldname, value := range p.Fields {
   538  				if fieldname == field {
   539  					_, ok := value.(int64)
   540  					return ok
   541  				}
   542  			}
   543  		}
   544  	}
   545  
   546  	return false
   547  }
   548  
   549  // HasInt32Field returns true if the measurement has an Int value
   550  func (a *Accumulator) HasInt32Field(measurement string, field string) bool {
   551  	a.Lock()
   552  	defer a.Unlock()
   553  	for _, p := range a.Metrics {
   554  		if p.Measurement == measurement {
   555  			for fieldname, value := range p.Fields {
   556  				if fieldname == field {
   557  					_, ok := value.(int32)
   558  					return ok
   559  				}
   560  			}
   561  		}
   562  	}
   563  
   564  	return false
   565  }
   566  
   567  // HasStringField returns true if the measurement has a String value
   568  func (a *Accumulator) HasStringField(measurement string, field string) bool {
   569  	a.Lock()
   570  	defer a.Unlock()
   571  	for _, p := range a.Metrics {
   572  		if p.Measurement == measurement {
   573  			for fieldname, value := range p.Fields {
   574  				if fieldname == field {
   575  					_, ok := value.(string)
   576  					return ok
   577  				}
   578  			}
   579  		}
   580  	}
   581  
   582  	return false
   583  }
   584  
   585  // HasUIntField returns true if the measurement has a UInt value
   586  func (a *Accumulator) HasUIntField(measurement string, field string) bool {
   587  	a.Lock()
   588  	defer a.Unlock()
   589  	for _, p := range a.Metrics {
   590  		if p.Measurement == measurement {
   591  			for fieldname, value := range p.Fields {
   592  				if fieldname == field {
   593  					_, ok := value.(uint64)
   594  					return ok
   595  				}
   596  			}
   597  		}
   598  	}
   599  
   600  	return false
   601  }
   602  
   603  // HasFloatField returns true if the given measurement has a float value
   604  func (a *Accumulator) HasFloatField(measurement string, field string) bool {
   605  	a.Lock()
   606  	defer a.Unlock()
   607  	for _, p := range a.Metrics {
   608  		if p.Measurement == measurement {
   609  			for fieldname, value := range p.Fields {
   610  				if fieldname == field {
   611  					_, ok := value.(float64)
   612  					return ok
   613  				}
   614  			}
   615  		}
   616  	}
   617  
   618  	return false
   619  }
   620  
   621  // HasMeasurement returns true if the accumulator has a measurement with the
   622  // given name
   623  func (a *Accumulator) HasMeasurement(measurement string) bool {
   624  	a.Lock()
   625  	defer a.Unlock()
   626  	for _, p := range a.Metrics {
   627  		if p.Measurement == measurement {
   628  			return true
   629  		}
   630  	}
   631  	return false
   632  }
   633  
   634  // IntField returns the int value of the given measurement and field or false.
   635  func (a *Accumulator) IntField(measurement string, field string) (int, bool) {
   636  	a.Lock()
   637  	defer a.Unlock()
   638  	for _, p := range a.Metrics {
   639  		if p.Measurement == measurement {
   640  			for fieldname, value := range p.Fields {
   641  				if fieldname == field {
   642  					v, ok := value.(int)
   643  					return v, ok
   644  				}
   645  			}
   646  		}
   647  	}
   648  
   649  	return 0, false
   650  }
   651  
   652  // Int64Field returns the int64 value of the given measurement and field or false.
   653  func (a *Accumulator) Int64Field(measurement string, field string) (int64, bool) {
   654  	a.Lock()
   655  	defer a.Unlock()
   656  	for _, p := range a.Metrics {
   657  		if p.Measurement == measurement {
   658  			for fieldname, value := range p.Fields {
   659  				if fieldname == field {
   660  					v, ok := value.(int64)
   661  					return v, ok
   662  				}
   663  			}
   664  		}
   665  	}
   666  
   667  	return 0, false
   668  }
   669  
   670  // Uint64Field returns the int64 value of the given measurement and field or false.
   671  func (a *Accumulator) Uint64Field(measurement string, field string) (uint64, bool) {
   672  	a.Lock()
   673  	defer a.Unlock()
   674  	for _, p := range a.Metrics {
   675  		if p.Measurement == measurement {
   676  			for fieldname, value := range p.Fields {
   677  				if fieldname == field {
   678  					v, ok := value.(uint64)
   679  					return v, ok
   680  				}
   681  			}
   682  		}
   683  	}
   684  
   685  	return 0, false
   686  }
   687  
   688  // Int32Field returns the int32 value of the given measurement and field or false.
   689  func (a *Accumulator) Int32Field(measurement string, field string) (int32, bool) {
   690  	a.Lock()
   691  	defer a.Unlock()
   692  	for _, p := range a.Metrics {
   693  		if p.Measurement == measurement {
   694  			for fieldname, value := range p.Fields {
   695  				if fieldname == field {
   696  					v, ok := value.(int32)
   697  					return v, ok
   698  				}
   699  			}
   700  		}
   701  	}
   702  
   703  	return 0, false
   704  }
   705  
   706  // FloatField returns the float64 value of the given measurement and field or false.
   707  func (a *Accumulator) FloatField(measurement string, field string) (float64, bool) {
   708  	a.Lock()
   709  	defer a.Unlock()
   710  	for _, p := range a.Metrics {
   711  		if p.Measurement == measurement {
   712  			for fieldname, value := range p.Fields {
   713  				if fieldname == field {
   714  					v, ok := value.(float64)
   715  					return v, ok
   716  				}
   717  			}
   718  		}
   719  	}
   720  
   721  	return 0.0, false
   722  }
   723  
   724  // StringField returns the string value of the given measurement and field or false.
   725  func (a *Accumulator) StringField(measurement string, field string) (string, bool) {
   726  	a.Lock()
   727  	defer a.Unlock()
   728  	for _, p := range a.Metrics {
   729  		if p.Measurement == measurement {
   730  			for fieldname, value := range p.Fields {
   731  				if fieldname == field {
   732  					v, ok := value.(string)
   733  					return v, ok
   734  				}
   735  			}
   736  		}
   737  	}
   738  	return "", false
   739  }
   740  
   741  // BoolField returns the bool value of the given measurement and field or false.
   742  func (a *Accumulator) BoolField(measurement string, field string) (v bool, ok bool) {
   743  	a.Lock()
   744  	defer a.Unlock()
   745  	for _, p := range a.Metrics {
   746  		if p.Measurement == measurement {
   747  			for fieldname, value := range p.Fields {
   748  				if fieldname == field {
   749  					v, ok = value.(bool)
   750  					return v, ok
   751  				}
   752  			}
   753  		}
   754  	}
   755  
   756  	return false, false
   757  }
   758  
   759  // NopAccumulator is used for benchmarking to isolate the plugin from the internal
   760  // telegraf accumulator machinery.
   761  type NopAccumulator struct{}
   762  
   763  func (n *NopAccumulator) AddFields(_ string, _ map[string]interface{}, _ map[string]string, _ ...time.Time) {
   764  }
   765  func (n *NopAccumulator) AddGauge(_ string, _ map[string]interface{}, _ map[string]string, _ ...time.Time) {
   766  }
   767  func (n *NopAccumulator) AddCounter(_ string, _ map[string]interface{}, _ map[string]string, _ ...time.Time) {
   768  }
   769  func (n *NopAccumulator) AddSummary(_ string, _ map[string]interface{}, _ map[string]string, _ ...time.Time) {
   770  }
   771  func (n *NopAccumulator) AddHistogram(_ string, _ map[string]interface{}, _ map[string]string, _ ...time.Time) {
   772  }
   773  func (n *NopAccumulator) AddMetric(telegraf.Metric)                       {}
   774  func (n *NopAccumulator) SetPrecision(_ time.Duration)                    {}
   775  func (n *NopAccumulator) AddError(_ error)                                {}
   776  func (n *NopAccumulator) WithTracking(_ int) telegraf.TrackingAccumulator { return nil }