@@ -11,6 +11,7 @@ import (
1111 "strings"
1212 "time"
1313
14+ "github.com/grafana/synthetic-monitoring-agent/internal/recall"
1415 "github.com/grafana/synthetic-monitoring-agent/internal/secrets"
1516
1617 kitlog "github.com/go-kit/kit/log" //nolint:staticcheck // TODO(mem): replace in BBE
@@ -82,6 +83,7 @@ type Scraper struct {
8283 histograms map [uint64 ]prometheus.Histogram
8384 telemeter Telemeter
8485 cals TenantCals
86+ recaller recall.Recaller
8587}
8688
8789type Factory func (
@@ -94,6 +96,7 @@ type Factory func(
9496 telemeter * telemetry.Telemeter ,
9597 secretStore secrets.SecretProvider ,
9698 cals TenantCals ,
99+ recaller recall.Recaller ,
97100) (* Scraper , error )
98101
99102type (
@@ -129,6 +132,7 @@ func New(
129132 telemeter * telemetry.Telemeter ,
130133 secretStore secrets.SecretProvider ,
131134 cals TenantCals ,
135+ recaller recall.Recaller ,
132136) (* Scraper , error ) {
133137 return NewWithOpts (ctx , check , ScraperOpts {
134138 Probe : probe ,
@@ -139,6 +143,7 @@ func New(
139143 LabelsLimiter : labelsLimiter ,
140144 Telemeter : telemeter ,
141145 CostAttributionLabels : cals ,
146+ Recaller : recaller ,
142147 })
143148}
144149
@@ -153,6 +158,7 @@ type ScraperOpts struct {
153158 LabelsLimiter LabelsLimiter
154159 Telemeter Telemeter
155160 CostAttributionLabels TenantCals
161+ Recaller recall.Recaller
156162}
157163
158164func NewWithOpts (ctx context.Context , check model.Check , opts ScraperOpts ) (* Scraper , error ) {
@@ -191,6 +197,7 @@ func NewWithOpts(ctx context.Context, check model.Check, opts ScraperOpts) (*Scr
191197 histograms : make (map [uint64 ]prometheus.Histogram ),
192198 telemeter : opts .Telemeter ,
193199 cals : opts .CostAttributionLabels ,
200+ recaller : opts .Recaller ,
194201 }, nil
195202}
196203
@@ -241,15 +248,28 @@ func (s *Scraper) Run(ctx context.Context) {
241248 // TODO(mem): keep count of the number of successive errors and
242249 // collect logs if threshold is reached.
243250
244- var (
245- frequency = ms (s .check .Frequency )
246- offset = ms (s .check .Offset )
247- )
251+ frequency := ms (s .check .Frequency )
252+
253+ recallCtx , cancelRecall := context .WithTimeout (ctx , 5 * time .Second )
254+ defer cancelRecall ()
255+
256+ lastRun , err := s .recaller .Recall (recallCtx , s .check .Id )
257+ if err != nil {
258+ s .logger .Error ().Err (err ).Msg ("could not fetch time for last run" )
259+ }
260+
261+ offset := time .Until (lastRun .Add (frequency ))
248262
249- if offset == 0 {
263+ if offset < 0 {
264+ s .logger .Debug ().Msg ("no last run found for check, assuming it was never run" )
250265 offset = randDuration (min (frequency , maxPublishInterval ))
251266 }
252267
268+ if configOffset := ms (s .check .Offset ); configOffset != 0 {
269+ s .logger .Debug ().Dur ("configOffset" , configOffset ).Dur ("computedOffset" , offset ).
270+ Msg ("Using fixed offset from config instead of computed one" )
271+ }
272+
253273 scrapeHandler := scrapeHandler {scraper : s }
254274
255275 tickWithOffset (
@@ -274,11 +294,17 @@ type scrapeHandler struct {
274294func (h * scrapeHandler ) scrape (ctx context.Context , t time.Time ) {
275295 h .scraper .metrics .AddScrape ()
276296
277- var (
278- err error
279- duration time.Duration
280- )
297+ recallCtx , cancelRecall := context .WithTimeout (ctx , 5 * time .Second )
298+ defer cancelRecall ()
299+
300+ // Record time of last execution, for as long as 2x frequency of the check. Past that it's really not worth keeping,
301+ // as we'd need to run it as soon as possible anyway.
302+ err := h .scraper .recaller .Remember (recallCtx , h .scraper .check .Id , 2 * ms (h .scraper .check .Frequency ))
303+ if err != nil {
304+ h .scraper .logger .Warn ().Err (err ).Msg ("could not store last execution time" )
305+ }
281306
307+ var duration time.Duration
282308 h .payload , duration , err = h .scraper .collectData (ctx , t )
283309
284310 switch {
0 commit comments