Skip to content
This repository has been archived by the owner on Jul 12, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2 from willnewrelic/product-user-agent
Browse files Browse the repository at this point in the history
Add Product to Config and User-Agent
  • Loading branch information
willnewrelic authored Dec 26, 2019
2 parents 44f8d4d + c5a7e13 commit dd46f57
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 19 deletions.
17 changes: 17 additions & 0 deletions telemetry/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ type Config struct {
MetricsURLOverride string
// SpansURLOverride overrides the spans endpoint if not not empty.
SpansURLOverride string
// Product is added to the User-Agent header. eg. "NewRelic-Go-OpenCensus"
Product string
// ProductVersion is added to the User-Agent header. eg. "0.1.0".
ProductVersion string
}

// ConfigAPIKey sets the Config's APIKey which is required.
Expand Down Expand Up @@ -153,3 +157,16 @@ func (cfg *Config) metricURL() string {
}
return defaultMetricURL
}

// userAgent creates the User-Agent header version according to the spec here:
// https://github.com/newrelic/newrelic-telemetry-sdk-specs/blob/master/communication.md#user-agent
func (cfg *Config) userAgent() string {
agent := "NewRelic-Go-TelemetrySDK/" + version
if "" != cfg.Product {
agent += " " + cfg.Product
if "" != cfg.ProductVersion {
agent += "/" + cfg.ProductVersion
}
}
return agent
}
43 changes: 43 additions & 0 deletions telemetry/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,46 @@ func TestConfigSpanURL(t *testing.T) {
t.Fatal(u)
}
}

func TestConfigUserAgent(t *testing.T) {
testcases := []struct {
option func(*Config)
expect string
}{
{
option: func(*Config) {},
expect: "NewRelic-Go-TelemetrySDK/" + version,
},
{
option: func(cfg *Config) {
cfg.Product = "myProduct"
},
expect: "NewRelic-Go-TelemetrySDK/" + version + " myProduct",
},
{
option: func(cfg *Config) {
cfg.Product = "myProduct"
cfg.ProductVersion = "0.1.0"
},
expect: "NewRelic-Go-TelemetrySDK/" + version + " myProduct/0.1.0",
},
{
option: func(cfg *Config) {
// Only use ProductVersion if Product is set.
cfg.ProductVersion = "0.1.0"
},
expect: "NewRelic-Go-TelemetrySDK/" + version,
},
}

for idx, tc := range testcases {
h, err := NewHarvester(configTesting, tc.option)
if nil == h || err != nil {
t.Fatal(h, err)
}
agent := h.config.userAgent()
if agent != tc.expect {
t.Error(idx, tc.expect, agent)
}
}
}
4 changes: 2 additions & 2 deletions telemetry/harvester.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ func (h *Harvester) swapOutMetrics(now time.Time) []request {
AttributesJSON: h.commonAttributesJSON,
Metrics: rawMetrics,
}
reqs, err := newRequests(batch, h.config.APIKey, h.config.metricURL())
reqs, err := newRequests(batch, h.config.APIKey, h.config.metricURL(), h.config.userAgent())
if nil != err {
h.config.logError(map[string]interface{}{
"err": err.Error(),
Expand All @@ -259,7 +259,7 @@ func (h *Harvester) swapOutSpans() []request {
AttributesJSON: h.commonAttributesJSON,
Spans: sps,
}
reqs, err := newRequests(batch, h.config.APIKey, h.config.spanURL())
reqs, err := newRequests(batch, h.config.APIKey, h.config.spanURL(), h.config.userAgent())
if nil != err {
h.config.logError(map[string]interface{}{
"err": err.Error(),
Expand Down
14 changes: 9 additions & 5 deletions telemetry/harvester_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,11 @@ func TestHarvestCancelled(t *testing.T) {
}

func TestNewRequestHeaders(t *testing.T) {
h, _ := NewHarvester(configTesting)
h, _ := NewHarvester(configTesting, func(cfg *Config) {
cfg.Product = "myProduct"
cfg.ProductVersion = "0.1.0"
})
expectUserAgent := "NewRelic-Go-TelemetrySDK/" + version + " myProduct/0.1.0"
h.RecordSpan(Span{TraceID: "id", ID: "id"})
h.RecordMetric(Gauge{})

Expand All @@ -164,8 +168,8 @@ func TestNewRequestHeaders(t *testing.T) {
if h := req.Request.Header.Get("Content-Encoding"); "gzip" != h {
t.Error("incorrect Content-Encoding header", req.Request.Header)
}
if h := req.Request.Header.Get("User-Agent"); "" == h {
t.Error("User-Agent header not found", req.Request.Header)
if h := req.Request.Header.Get("User-Agent"); expectUserAgent != h {
t.Error("User-Agent header incorrect", req.Request.Header)
}

reqs = h.swapOutMetrics(time.Now())
Expand All @@ -182,8 +186,8 @@ func TestNewRequestHeaders(t *testing.T) {
if h := req.Request.Header.Get("Content-Encoding"); "gzip" != h {
t.Error("incorrect Content-Encoding header", h)
}
if h := req.Request.Header.Get("User-Agent"); "" == h {
t.Error("User-Agent header not found", h)
if h := req.Request.Header.Get("User-Agent"); expectUserAgent != h {
t.Error("User-Agent header incorrect", h)
}
}

Expand Down
4 changes: 2 additions & 2 deletions telemetry/metrics_batch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func TestMetrics(t *testing.T) {
]
}]`)

reqs, err := newRequests(metrics, "my-api-key", defaultMetricURL)
reqs, err := newRequests(metrics, "my-api-key", defaultMetricURL, "userAgent")
if err != nil {
t.Error("error creating request", err)
}
Expand Down Expand Up @@ -113,7 +113,7 @@ func testBatchJSON(t testing.TB, batch *metricBatch, expect string) {
if th, ok := t.(interface{ Helper() }); ok {
th.Helper()
}
reqs, err := newRequests(batch, "my-api-key", defaultMetricURL)
reqs, err := newRequests(batch, "my-api-key", defaultMetricURL, "userAgent")
if nil != err {
t.Fatal(err)
}
Expand Down
10 changes: 5 additions & 5 deletions telemetry/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ func requestNeedsSplit(r request) bool {
return r.compressedBodyLength >= maxCompressedSizeBytes
}

func newRequests(batch requestsBuilder, apiKey string, url string) ([]request, error) {
return newRequestsInternal(batch, apiKey, url, requestNeedsSplit)
func newRequests(batch requestsBuilder, apiKey string, url string, userAgent string) ([]request, error) {
return newRequestsInternal(batch, apiKey, url, userAgent, requestNeedsSplit)
}

func newRequestsInternal(batch requestsBuilder, apiKey string, url string, needsSplit func(request) bool) ([]request, error) {
func newRequestsInternal(batch requestsBuilder, apiKey string, url string, userAgent string, needsSplit func(request) bool) ([]request, error) {
uncompressed := batch.makeBody()
compressed, err := internal.Compress(uncompressed)
if nil != err {
Expand All @@ -56,7 +56,7 @@ func newRequestsInternal(batch requestsBuilder, apiKey string, url string, needs
req.Header.Add("Content-Type", "application/json")
req.Header.Add("Api-Key", apiKey)
req.Header.Add("Content-Encoding", "gzip")
req.Header.Add("User-Agent", "NewRelic-Go-TelemetrySDK/"+version)
req.Header.Add("User-Agent", userAgent)
r := request{
Request: req,
UncompressedBody: uncompressed,
Expand All @@ -74,7 +74,7 @@ func newRequestsInternal(batch requestsBuilder, apiKey string, url string, needs
}

for _, b := range batches {
rs, err := newRequestsInternal(b, apiKey, url, needsSplit)
rs, err := newRequestsInternal(b, apiKey, url, userAgent, needsSplit)
if nil != err {
return nil, err
}
Expand Down
8 changes: 4 additions & 4 deletions telemetry/request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func TestNewRequestsSplitSuccess(t *testing.T) {
json.RawMessage(`123456789`),
},
}
reqs, err := newRequestsInternal(ts, "", "", func(r request) bool {
reqs, err := newRequestsInternal(ts, "", "", "", func(r request) bool {
return len(r.UncompressedBody) >= 10
})
if err != nil {
Expand All @@ -56,7 +56,7 @@ func TestNewRequestsCantSplit(t *testing.T) {
json.RawMessage(`12345678901`),
},
}
reqs, err := newRequestsInternal(ts, "", "", func(r request) bool {
reqs, err := newRequestsInternal(ts, "", "", "", func(r request) bool {
return len(r.UncompressedBody) >= 10
})
if err != errUnableToSplit {
Expand All @@ -78,7 +78,7 @@ func randomJSON(numBytes int) json.RawMessage {

func TestLargeRequestNeedsSplit(t *testing.T) {
js := randomJSON(4 * maxCompressedSizeBytes)
reqs, err := newRequests(testRequestBuilder{bodies: []json.RawMessage{js}}, "apiKey", defaultMetricURL)
reqs, err := newRequests(testRequestBuilder{bodies: []json.RawMessage{js}}, "apiKey", defaultMetricURL, "userAgent")
if reqs != nil {
t.Error(reqs)
}
Expand All @@ -89,7 +89,7 @@ func TestLargeRequestNeedsSplit(t *testing.T) {

func TestLargeRequestNoSplit(t *testing.T) {
js := randomJSON(maxCompressedSizeBytes / 2)
reqs, err := newRequests(testRequestBuilder{bodies: []json.RawMessage{js}}, "apiKey", defaultMetricURL)
reqs, err := newRequests(testRequestBuilder{bodies: []json.RawMessage{js}}, "apiKey", defaultMetricURL, "userAgent")
if err != nil {
t.Fatal(err)
}
Expand Down
2 changes: 1 addition & 1 deletion telemetry/spans_batch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func testSpanBatchJSON(t testing.TB, batch *spanBatch, expect string) {
if th, ok := t.(interface{ Helper() }); ok {
th.Helper()
}
reqs, err := newRequests(batch, "apiKey", defaultSpanURL)
reqs, err := newRequests(batch, "apiKey", defaultSpanURL, "userAgent")
if nil != err {
t.Fatal(err)
}
Expand Down

0 comments on commit dd46f57

Please sign in to comment.