github.com/newrelic/go-agent@v3.26.0+incompatible/internal/queuing.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package internal 5 6 import ( 7 "net/http" 8 "strconv" 9 "strings" 10 "time" 11 ) 12 13 const ( 14 xRequestStart = "X-Request-Start" 15 xQueueStart = "X-Queue-Start" 16 ) 17 18 var ( 19 earliestAcceptableSeconds = time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC).Unix() 20 latestAcceptableSeconds = time.Date(2050, time.January, 1, 0, 0, 0, 0, time.UTC).Unix() 21 ) 22 23 func checkQueueTimeSeconds(secondsFloat float64) time.Time { 24 seconds := int64(secondsFloat) 25 nanos := int64((secondsFloat - float64(seconds)) * (1000.0 * 1000.0 * 1000.0)) 26 if seconds > earliestAcceptableSeconds && seconds < latestAcceptableSeconds { 27 return time.Unix(seconds, nanos) 28 } 29 return time.Time{} 30 } 31 32 func parseQueueTime(s string) time.Time { 33 f, err := strconv.ParseFloat(s, 64) 34 if nil != err { 35 return time.Time{} 36 } 37 if f <= 0 { 38 return time.Time{} 39 } 40 41 // try microseconds 42 if t := checkQueueTimeSeconds(f / (1000.0 * 1000.0)); !t.IsZero() { 43 return t 44 } 45 // try milliseconds 46 if t := checkQueueTimeSeconds(f / (1000.0)); !t.IsZero() { 47 return t 48 } 49 // try seconds 50 if t := checkQueueTimeSeconds(f); !t.IsZero() { 51 return t 52 } 53 return time.Time{} 54 } 55 56 // QueueDuration TODO 57 func QueueDuration(hdr http.Header, txnStart time.Time) time.Duration { 58 s := hdr.Get(xQueueStart) 59 if "" == s { 60 s = hdr.Get(xRequestStart) 61 } 62 if "" == s { 63 return 0 64 } 65 66 s = strings.TrimPrefix(s, "t=") 67 qt := parseQueueTime(s) 68 if qt.IsZero() { 69 return 0 70 } 71 if qt.After(txnStart) { 72 return 0 73 } 74 return txnStart.Sub(qt) 75 }