github.com/newrelic/go-agent@v3.26.0+incompatible/internal/utilities.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  	"bytes"
     8  	"encoding/json"
     9  	"fmt"
    10  	"net/http"
    11  	"strconv"
    12  	"strings"
    13  	"time"
    14  )
    15  
    16  // JSONString assists in logging JSON:  Based on the formatter used to log
    17  // Context contents, the contents could be marshalled as JSON or just printed
    18  // directly.
    19  type JSONString string
    20  
    21  // MarshalJSON returns the JSONString unmodified without any escaping.
    22  func (js JSONString) MarshalJSON() ([]byte, error) {
    23  	if "" == js {
    24  		return []byte("null"), nil
    25  	}
    26  	return []byte(js), nil
    27  }
    28  
    29  func removeFirstSegment(name string) string {
    30  	idx := strings.Index(name, "/")
    31  	if -1 == idx {
    32  		return name
    33  	}
    34  	return name[idx+1:]
    35  }
    36  
    37  func timeToFloatSeconds(t time.Time) float64 {
    38  	return float64(t.UnixNano()) / float64(1000*1000*1000)
    39  }
    40  
    41  func timeToFloatMilliseconds(t time.Time) float64 {
    42  	return float64(t.UnixNano()) / float64(1000*1000)
    43  }
    44  
    45  // FloatSecondsToDuration turns a float64 in seconds into a time.Duration.
    46  func FloatSecondsToDuration(seconds float64) time.Duration {
    47  	nanos := seconds * 1000 * 1000 * 1000
    48  	return time.Duration(nanos) * time.Nanosecond
    49  }
    50  
    51  func absTimeDiff(t1, t2 time.Time) time.Duration {
    52  	if t1.After(t2) {
    53  		return t1.Sub(t2)
    54  	}
    55  	return t2.Sub(t1)
    56  }
    57  
    58  // CompactJSONString removes the whitespace from a JSON string.  This function
    59  // will panic if the string provided is not valid JSON.  Thus is must only be
    60  // used in testing code!
    61  func CompactJSONString(js string) string {
    62  	buf := new(bytes.Buffer)
    63  	if err := json.Compact(buf, []byte(js)); err != nil {
    64  		panic(fmt.Errorf("unable to compact JSON: %v", err))
    65  	}
    66  	return buf.String()
    67  }
    68  
    69  // GetContentLengthFromHeader gets the content length from a HTTP header, or -1
    70  // if no content length is available.
    71  func GetContentLengthFromHeader(h http.Header) int64 {
    72  	if cl := h.Get("Content-Length"); cl != "" {
    73  		if contentLength, err := strconv.ParseInt(cl, 10, 64); err == nil {
    74  			return contentLength
    75  		}
    76  	}
    77  
    78  	return -1
    79  }
    80  
    81  // StringLengthByteLimit truncates strings using a byte-limit boundary and
    82  // avoids terminating in the middle of a multibyte character.
    83  func StringLengthByteLimit(str string, byteLimit int) string {
    84  	if len(str) <= byteLimit {
    85  		return str
    86  	}
    87  
    88  	limitIndex := 0
    89  	for pos := range str {
    90  		if pos > byteLimit {
    91  			break
    92  		}
    93  		limitIndex = pos
    94  	}
    95  	return str[0:limitIndex]
    96  }
    97  
    98  func timeFromUnixMilliseconds(millis uint64) time.Time {
    99  	secs := int64(millis) / 1000
   100  	msecsRemaining := int64(millis) % 1000
   101  	nsecsRemaining := msecsRemaining * (1000 * 1000)
   102  	return time.Unix(secs, nsecsRemaining)
   103  }
   104  
   105  // TimeToUnixMilliseconds converts a time into a Unix timestamp in millisecond
   106  // units.
   107  func TimeToUnixMilliseconds(tm time.Time) uint64 {
   108  	return uint64(tm.UnixNano()) / uint64(1000*1000)
   109  }
   110  
   111  // MinorVersion takes a given version string and returns only the major and
   112  // minor portions of it. If the input is malformed, it returns the input
   113  // untouched.
   114  func MinorVersion(v string) string {
   115  	split := strings.SplitN(v, ".", 3)
   116  	if len(split) < 2 {
   117  		return v
   118  	}
   119  	return split[0] + "." + split[1]
   120  }