github.com/newrelic/go-agent@v3.26.0+incompatible/browser_header.go (about) 1 // Copyright 2020 New Relic Corporation. All rights reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 package newrelic 5 6 import ( 7 "encoding/json" 8 ) 9 10 var ( 11 browserStartTag = []byte(`<script type="text/javascript">`) 12 browserEndTag = []byte(`</script>`) 13 browserInfoPrefix = []byte(`window.NREUM||(NREUM={});NREUM.info=`) 14 ) 15 16 // browserInfo contains the fields that are marshalled into the Browser agent's 17 // info hash. 18 // 19 // https://newrelic.atlassian.net/wiki/spaces/eng/pages/50299103/BAM+Agent+Auto-Instrumentation 20 type browserInfo struct { 21 Beacon string `json:"beacon"` 22 LicenseKey string `json:"licenseKey"` 23 ApplicationID string `json:"applicationID"` 24 TransactionName string `json:"transactionName"` 25 QueueTimeMillis int64 `json:"queueTime"` 26 ApplicationTimeMillis int64 `json:"applicationTime"` 27 ObfuscatedAttributes string `json:"atts"` 28 ErrorBeacon string `json:"errorBeacon"` 29 Agent string `json:"agent"` 30 } 31 32 // BrowserTimingHeader encapsulates the JavaScript required to enable New 33 // Relic's Browser product. 34 type BrowserTimingHeader struct { 35 agentLoader string 36 info browserInfo 37 } 38 39 func appendSlices(slices ...[]byte) []byte { 40 length := 0 41 for _, s := range slices { 42 length += len(s) 43 } 44 combined := make([]byte, 0, length) 45 for _, s := range slices { 46 combined = append(combined, s...) 47 } 48 return combined 49 } 50 51 // WithTags returns the browser timing JavaScript which includes the enclosing 52 // <script> and </script> tags. This method returns nil if the receiver is 53 // nil, the feature is disabled, the application is not yet connected, or an 54 // error occurs. The byte slice returned is in UTF-8 format. 55 func (h *BrowserTimingHeader) WithTags() []byte { 56 withoutTags := h.WithoutTags() 57 if nil == withoutTags { 58 return nil 59 } 60 return appendSlices(browserStartTag, withoutTags, browserEndTag) 61 } 62 63 // WithoutTags returns the browser timing JavaScript without any enclosing tags, 64 // which may then be embedded within any JavaScript code. This method returns 65 // nil if the receiver is nil, the feature is disabled, the application is not 66 // yet connected, or an error occurs. The byte slice returned is in UTF-8 67 // format. 68 func (h *BrowserTimingHeader) WithoutTags() []byte { 69 if nil == h { 70 return nil 71 } 72 73 // We could memoise this, but it seems unnecessary, since most users are 74 // going to call this zero or one times. 75 info, err := json.Marshal(h.info) 76 if err != nil { 77 // There's no way to log from here, but this also should be unreachable in 78 // practice. 79 return nil 80 } 81 82 return appendSlices([]byte(h.agentLoader), browserInfoPrefix, info) 83 }