go.undefinedlabs.com/scopeagent@v0.4.2/agent/ntp.go (about)

     1  package agent
     2  
     3  import (
     4  	"github.com/beevik/ntp"
     5  	"sync"
     6  	"time"
     7  )
     8  
     9  const (
    10  	server  = "pool.ntp.org"
    11  	retries = 5
    12  	timeout = 2 * time.Second
    13  	backoff = 1 * time.Second
    14  )
    15  
    16  var (
    17  	ntpOffset time.Duration
    18  	once      sync.Once
    19  )
    20  
    21  // Gets the NTP offset from the ntp server pool
    22  func getNTPOffset() (time.Duration, error) {
    23  	var ntpError error = nil
    24  	for i := 1; i <= retries; i++ {
    25  		r, err := ntp.QueryWithOptions(server, ntp.QueryOptions{Timeout: timeout})
    26  		if err == nil {
    27  			return r.ClockOffset, nil
    28  		}
    29  		ntpError = err
    30  		time.Sleep(backoff)
    31  	}
    32  	return 0, ntpError
    33  }
    34  
    35  // Applies the NTP offset to the given time
    36  func (r *SpanRecorder) applyNTPOffset(t time.Time) time.Time {
    37  	once.Do(func() {
    38  		if r.debugMode {
    39  			r.logger.Println("calculating ntp offset.")
    40  		}
    41  		offset := r.cache.GetOrSet("ntp", true, func(d interface{}, s string) interface{} {
    42  			oSet, err := getNTPOffset()
    43  			if err != nil {
    44  				r.logger.Printf("error calculating the ntp offset: %v\n", err)
    45  				return nil
    46  			}
    47  			return float64(oSet)
    48  		})
    49  		if offset != nil {
    50  			ntpOffset = time.Duration(offset.(float64))
    51  			r.logger.Printf("ntp offset: %v\n", ntpOffset)
    52  		}
    53  	})
    54  	return t.Add(ntpOffset)
    55  }