github.com/grafana/synthetic-monitoring-agent@v0.64.2/internal/scraper/scrape_clock.go (about)

     1  package scraper
     2  
     3  import (
     4  	"time"
     5  
     6  	kitlog "github.com/go-kit/log"
     7  )
     8  
     9  // scrapeClock decides how a single scrape's telemetry is timestamped. The
    10  // scheduled scraper and unscheduled collector select different policies at
    11  // their entry points, while the scrape pipeline remains caller-agnostic.
    12  type scrapeClock interface {
    13  	// wrapperLogTimestamp is the kitlog Valuer for the wrapper-log `ts` field.
    14  	// extractLogs turns that field into each Loki entry's timestamp, so it
    15  	// governs where logs without their own `time` field land.
    16  	wrapperLogTimestamp() kitlog.Valuer
    17  	// endLogFields returns any extra fields appended to the terminal
    18  	// (succeeded/failed) wrapper log, e.g. an event-end `time` that overrides
    19  	// `ts` for that line.
    20  	endLogFields(duration float64) []any
    21  	// fallbackDuration computes the probe duration when the prober reports none.
    22  	fallbackDuration(wallStart time.Time) time.Duration
    23  }
    24  
    25  // wallClock is the scheduled scraper's policy: real-time log timestamps and a
    26  // duration fallback measured from the scrape's nominal time.
    27  type wallClock struct {
    28  	scheduledAt time.Time
    29  }
    30  
    31  func scheduledScrapeClock(scheduledAt time.Time) scrapeClock {
    32  	return wallClock{scheduledAt: scheduledAt}
    33  }
    34  
    35  func (wallClock) wrapperLogTimestamp() kitlog.Valuer { return kitlog.DefaultTimestampUTC }
    36  
    37  func (wallClock) endLogFields(float64) []any { return nil }
    38  
    39  // fallbackDuration deliberately ignores wallStart: measuring from the scrape's
    40  // nominal time is the scheduled path's pre-existing behavior.
    41  func (w wallClock) fallbackDuration(time.Time) time.Duration {
    42  	return time.Since(w.scheduledAt)
    43  }
    44  
    45  // logicalClock places a scrape's telemetry at a caller-supplied event time,
    46  // which may be arbitrarily far in the past: the wrapper `ts` is pinned to
    47  // eventTime and the terminal log is shifted to eventTime+duration, while the
    48  // duration fallback still measures real elapsed time.
    49  type logicalClock struct {
    50  	eventTime time.Time
    51  }
    52  
    53  func logicalScrapeClock(eventTime time.Time) scrapeClock {
    54  	return logicalClock{eventTime: eventTime}
    55  }
    56  
    57  func (l logicalClock) wrapperLogTimestamp() kitlog.Valuer {
    58  	return kitlog.TimestampFormat(l.eventTime.UTC, time.RFC3339Nano)
    59  }
    60  
    61  func (l logicalClock) endLogFields(duration float64) []any {
    62  	eventEnd := l.eventTime.Add(time.Duration(duration * float64(time.Second)))
    63  	return []any{"time", eventEnd.UTC().Format(time.RFC3339Nano)}
    64  }
    65  
    66  func (logicalClock) fallbackDuration(wallStart time.Time) time.Duration {
    67  	return time.Since(wallStart)
    68  }