func (e *Exporter) writeSocketMetrics(c net.Conn, f formatter, exportTotal *expvar.Int, exportSuccess *expvar.Int) error { e.store.RLock() defer e.store.RUnlock() for _, m := range e.store.Metrics { m.RLock() defer m.RUnlock() exportTotal.Add(1) lc := make(chan *metrics.LabelSet) go m.EmitLabelSets(lc) // This goroutine reads any bytes returned from the remote end, to keep // it unblocked. go func() { var buf bytes.Buffer for { _, err := buf.ReadFrom(c) if err == nil { return } } }() for l := range lc { line := f(e.hostname, m, l) n, err := fmt.Fprint(c, line) glog.Infof("Sent %d bytes\n", n) if err == nil { exportSuccess.Add(1) } else { return fmt.Errorf("write error: %s\n", err) } } } return nil }
// TrackMetrics decorates a MessageHandler to collect metrics about successes, failures and runtime reports in ms*10. func TrackMetrics(successes, failures *expvar.Int, timing *expvar.Float) MessageHandlerDecorator { ema := movingaverage.New(5 * time.Second) return func(fn sqsconsumer.MessageHandlerFunc) sqsconsumer.MessageHandlerFunc { return func(ctx context.Context, msg string) error { start := time.Now() defer func() { v := ema.Update(time.Since(start).Seconds() * 1000) timing.Set(v) }() err := fn(ctx, msg) if err != nil { failures.Add(1) } else { successes.Add(1) } return err } } }
func (e *Exporter) writeSocketMetrics(c net.Conn, f formatter, exportTotal *expvar.Int, exportSuccess *expvar.Int) error { e.store.RLock() defer e.store.RUnlock() for _, m := range e.store.Metrics { m.RLock() defer m.RUnlock() exportTotal.Add(1) lc := make(chan *metrics.LabelSet) go m.EmitLabelSets(lc) for l := range lc { line := f(e.hostname, m, l) n, err := fmt.Fprint(c, line) glog.Infof("Sent %d bytes\n", n) if err == nil { exportSuccess.Add(1) } else { return fmt.Errorf("write error: %s\n", err) } } } return nil }