in exporter/collector/metrics.go [666:711]
func (me *MetricsExporter) runWALReadAndExportLoop(ctx context.Context) {
defer me.goroutines.Done()
defer func() {
if err := me.wal.Close(); err != nil {
me.obs.log.Error(fmt.Sprintf("error closing WAL: %+v\n", err))
}
}()
for {
select {
case <-ctx.Done():
return
case <-me.shutdownC:
// do one last final read/export then return
// otherwise the runner goroutine could leave some hanging metrics unexported
for {
err := me.readWALAndExport(ctx)
if err != nil {
if !errors.Is(err, wal.ErrOutOfRange) {
me.obs.log.Error(fmt.Sprintf("error flushing remaining WAL entries: %+v", err))
}
break
}
}
return
default:
err := me.readWALAndExport(ctx)
if err == nil {
continue
}
// ErrNotFound from wal.Read() means the index is either 0 or out of
// bounds (indicating we're probably at the end of the WAL). That error
// will trigger a file watch for new writes (below this). For other
// errors, fail.
// ErrNotFound can be expected occasionally if we've reached the end of
// the WAL, so don't bother logging those.
if !errors.Is(err, wal.ErrNotFound) {
me.obs.log.Error(fmt.Sprintf("error reading WAL and exporting: %+v", err))
}
// Must have been ErrNotFound, start a file watch and block waiting for updates.
if err = me.watchWALFile(ctx); err != nil {
me.obs.log.Error(fmt.Sprintf("error watching WAL and exporting: %+v", err))
}
}
}
}