// flusher monitors the metrics input channel and flushes on the minimum interval func (a *Agent) flusher(shutdown chan struct{}, metricC chan telegraf.Metric) error { // Inelegant, but this sleep is to allow the Gather threads to run, so that // the flusher will flush after metrics are collected. time.Sleep(time.Millisecond * 200) ticker := time.NewTicker(a.Config.Agent.FlushInterval.Duration) for { select { case <-shutdown: log.Println("Hang on, flushing any cached metrics before shutdown") a.flush() return nil case <-ticker.C: internal.RandomSleep(a.Config.Agent.FlushJitter.Duration, shutdown) a.flush() case m := <-metricC: for i, o := range a.Config.Outputs { if i == len(a.Config.Outputs)-1 { o.AddMetric(m) } else { o.AddMetric(copyMetric(m)) } } } } }
// gatherer runs the inputs that have been configured with their own // reporting interval. func (a *Agent) gatherer( shutdown chan struct{}, input *models.RunningInput, interval time.Duration, metricC chan telegraf.Metric, ) { defer panicRecover(input) ticker := time.NewTicker(interval) defer ticker.Stop() for { acc := NewAccumulator(input, metricC) acc.SetPrecision(a.Config.Agent.Precision.Duration, a.Config.Agent.Interval.Duration) input.SetDebug(a.Config.Agent.Debug) input.SetDefaultTags(a.Config.Tags) internal.RandomSleep(a.Config.Agent.CollectionJitter.Duration, shutdown) start := time.Now() gatherWithTimeout(shutdown, input, acc, interval) elapsed := time.Since(start) log.Printf("D! Input [%s] gathered metrics, (%s interval) in %s\n", input.Name(), interval, elapsed) select { case <-shutdown: return case <-ticker.C: continue } } }
// gatherer runs the inputs that have been configured with their own // reporting interval. func (a *Agent) gatherer( shutdown chan struct{}, input *internal_models.RunningInput, interval time.Duration, metricC chan telegraf.Metric, ) error { defer panicRecover(input) ticker := time.NewTicker(interval) defer ticker.Stop() for { var outerr error acc := NewAccumulator(input.Config, metricC) acc.SetDebug(a.Config.Agent.Debug) acc.setDefaultTags(a.Config.Tags) internal.RandomSleep(a.Config.Agent.CollectionJitter.Duration, shutdown) start := time.Now() gatherWithTimeout(shutdown, input, acc, interval) elapsed := time.Since(start) if outerr != nil { return outerr } if a.Config.Agent.Debug { log.Printf("Input [%s] gathered metrics, (%s interval) in %s\n", input.Name, interval, elapsed) } select { case <-shutdown: return nil case <-ticker.C: continue } } }
// flusher monitors the metrics input channel and flushes on the minimum interval func (a *Agent) flusher(shutdown chan struct{}, metricC chan telegraf.Metric) error { // Inelegant, but this sleep is to allow the Gather threads to run, so that // the flusher will flush after metrics are collected. time.Sleep(time.Millisecond * 300) // create an output metric channel and a gorouting that continously passes // each metric onto the output plugins & aggregators. outMetricC := make(chan telegraf.Metric, 100) var wg sync.WaitGroup wg.Add(1) go func() { defer wg.Done() for { select { case <-shutdown: if len(outMetricC) > 0 { // keep going until outMetricC is flushed continue } return case m := <-outMetricC: // if dropOriginal is set to true, then we will only send this // metric to the aggregators, not the outputs. var dropOriginal bool if !m.IsAggregate() { for _, agg := range a.Config.Aggregators { if ok := agg.Add(copyMetric(m)); ok { dropOriginal = true } } } if !dropOriginal { for i, o := range a.Config.Outputs { if i == len(a.Config.Outputs)-1 { o.AddMetric(m) } else { o.AddMetric(copyMetric(m)) } } } } } }() ticker := time.NewTicker(a.Config.Agent.FlushInterval.Duration) for { select { case <-shutdown: log.Println("I! Hang on, flushing any cached metrics before shutdown") // wait for outMetricC to get flushed before flushing outputs wg.Wait() a.flush() return nil case <-ticker.C: internal.RandomSleep(a.Config.Agent.FlushJitter.Duration, shutdown) a.flush() case metric := <-metricC: // NOTE potential bottleneck here as we put each metric through the // processors serially. mS := []telegraf.Metric{metric} for _, processor := range a.Config.Processors { mS = processor.Apply(mS...) } for _, m := range mS { outMetricC <- m } } } }