From 6292b2282970028db446c95ef77d3bde9eb2f758 Mon Sep 17 00:00:00 2001 From: Anuraag Agrawal Date: Wed, 2 Jun 2021 11:07:41 +0900 Subject: [PATCH] Set Throttle in X-Ray exporter. --- exporter/awsxrayexporter/translator/cause.go | 11 ++++-- .../awsxrayexporter/translator/cause_test.go | 36 ++++++++++++++++--- .../awsxrayexporter/translator/segment.go | 23 ++++++------ .../translator/segment_test.go | 29 +++++++++++++++ 4 files changed, 80 insertions(+), 19 deletions(-) diff --git a/exporter/awsxrayexporter/translator/cause.go b/exporter/awsxrayexporter/translator/cause.go index d1e300aaac60..8e1190b892c3 100644 --- a/exporter/awsxrayexporter/translator/cause.go +++ b/exporter/awsxrayexporter/translator/cause.go @@ -27,11 +27,11 @@ import ( awsxray "github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/xray" ) -func makeCause(span pdata.Span, attributes map[string]string, resource pdata.Resource) (isError, isFault bool, +func makeCause(span pdata.Span, attributes map[string]string, resource pdata.Resource) (isError, isFault, isThrottle bool, filtered map[string]string, cause *awsxray.CauseData) { status := span.Status() if status.Code() != pdata.StatusCodeError { - return false, false, attributes, nil + return false, false, false, attributes, nil } filtered = attributes @@ -123,15 +123,20 @@ func makeCause(span pdata.Span, attributes map[string]string, resource pdata.Res if code >= 400 && code <= 499 { isError = true isFault = false + if code == 429 { + isThrottle = true + } } else { isError = false + isThrottle = false isFault = true } } else { isError = false + isThrottle = false isFault = true } - return isError, isFault, filtered, cause + return isError, isFault, isThrottle, filtered, cause } func parseException(exceptionType string, message string, stacktrace string, language string) []awsxray.Exception { diff --git a/exporter/awsxrayexporter/translator/cause_test.go b/exporter/awsxrayexporter/translator/cause_test.go index 1aa854bcdc72..6c9a141a429a 100644 --- a/exporter/awsxrayexporter/translator/cause_test.go +++ b/exporter/awsxrayexporter/translator/cause_test.go @@ -53,10 +53,11 @@ Caused by: java.lang.IllegalArgumentException: bad argument`) res := pdata.NewResource() res.Attributes().InsertString(semconventions.AttributeTelemetrySDKLanguage, "java") - isError, isFault, filteredResult, cause := makeCause(span, filtered, res) + isError, isFault, isThrottle, filteredResult, cause := makeCause(span, filtered, res) assert.True(t, isFault) assert.False(t, isError) + assert.False(t, isThrottle) assert.Equal(t, filtered, filteredResult) assert.NotNil(t, cause) assert.Len(t, cause.Exceptions, 3) @@ -82,10 +83,11 @@ func TestCauseWithStatusMessage(t *testing.T) { filtered, _ := makeHTTP(span) res := pdata.NewResource() - isError, isFault, filtered, cause := makeCause(span, filtered, res) + isError, isFault, isThrottle, filtered, cause := makeCause(span, filtered, res) assert.True(t, isFault) assert.False(t, isError) + assert.False(t, isThrottle) assert.NotNil(t, filtered) assert.NotNil(t, cause) w := testWriters.borrow() @@ -108,10 +110,11 @@ func TestCauseWithHttpStatusMessage(t *testing.T) { filtered, _ := makeHTTP(span) res := pdata.NewResource() - isError, isFault, filtered, cause := makeCause(span, filtered, res) + isError, isFault, isThrottle, filtered, cause := makeCause(span, filtered, res) assert.True(t, isFault) assert.False(t, isError) + assert.False(t, isThrottle) assert.NotNil(t, filtered) assert.NotNil(t, cause) w := testWriters.borrow() @@ -138,10 +141,11 @@ func TestCauseWithZeroStatusMessage(t *testing.T) { // marking a success status with an error http status code, and status wins. // We do not expect to see such spans in practice. res := pdata.NewResource() - isError, isFault, filtered, cause := makeCause(span, filtered, res) + isError, isFault, isThrottle, filtered, cause := makeCause(span, filtered, res) assert.False(t, isError) assert.False(t, isFault) + assert.False(t, isThrottle) assert.NotNil(t, filtered) assert.Nil(t, cause) } @@ -158,10 +162,32 @@ func TestCauseWithClientErrorMessage(t *testing.T) { filtered, _ := makeHTTP(span) res := pdata.NewResource() - isError, isFault, filtered, cause := makeCause(span, filtered, res) + isError, isFault, isThrottle, filtered, cause := makeCause(span, filtered, res) assert.True(t, isError) assert.False(t, isFault) + assert.False(t, isThrottle) + assert.NotNil(t, filtered) + assert.NotNil(t, cause) +} + +func TestCauseWithThrottled(t *testing.T) { + errorMsg := "this is a test" + attributes := make(map[string]interface{}) + attributes[semconventions.AttributeHTTPMethod] = "POST" + attributes[semconventions.AttributeHTTPURL] = "https://api.example.com/widgets" + attributes[semconventions.AttributeHTTPStatusCode] = 429 + attributes[semconventions.AttributeHTTPStatusText] = errorMsg + + span := constructExceptionServerSpan(attributes, pdata.StatusCodeError) + filtered, _ := makeHTTP(span) + + res := pdata.NewResource() + isError, isFault, isThrottle, filtered, cause := makeCause(span, filtered, res) + + assert.True(t, isError) + assert.False(t, isFault) + assert.True(t, isThrottle) assert.NotNil(t, filtered) assert.NotNil(t, cause) } diff --git a/exporter/awsxrayexporter/translator/segment.go b/exporter/awsxrayexporter/translator/segment.go index 027334adefc6..78ca77fd6230 100644 --- a/exporter/awsxrayexporter/translator/segment.go +++ b/exporter/awsxrayexporter/translator/segment.go @@ -97,17 +97,17 @@ func MakeSegment(span pdata.Span, resource pdata.Resource, indexedAttrs []string } var ( - startTime = timestampToFloatSeconds(span.StartTimestamp()) - endTime = timestampToFloatSeconds(span.EndTimestamp()) - httpfiltered, http = makeHTTP(span) - isError, isFault, causefiltered, cause = makeCause(span, httpfiltered, resource) - origin = determineAwsOrigin(resource) - awsfiltered, aws = makeAws(causefiltered, resource) - service = makeService(resource) - sqlfiltered, sql = makeSQL(awsfiltered) - user, annotations, metadata = makeXRayAttributes(sqlfiltered, resource, storeResource, indexedAttrs, indexAllAttrs) - name string - namespace string + startTime = timestampToFloatSeconds(span.StartTimestamp()) + endTime = timestampToFloatSeconds(span.EndTimestamp()) + httpfiltered, http = makeHTTP(span) + isError, isFault, isThrottle, causefiltered, cause = makeCause(span, httpfiltered, resource) + origin = determineAwsOrigin(resource) + awsfiltered, aws = makeAws(causefiltered, resource) + service = makeService(resource) + sqlfiltered, sql = makeSQL(awsfiltered) + user, annotations, metadata = makeXRayAttributes(sqlfiltered, resource, storeResource, indexedAttrs, indexAllAttrs) + name string + namespace string ) // X-Ray segment names are service names, unlike span names which are methods. Try to find a service name. @@ -185,6 +185,7 @@ func MakeSegment(span pdata.Span, resource pdata.Resource, indexedAttrs []string ParentID: awsxray.String(span.ParentSpanID().HexString()), Fault: awsP.Bool(isFault), Error: awsP.Bool(isError), + Throttle: awsP.Bool(isThrottle), Cause: cause, Origin: awsxray.String(origin), Namespace: awsxray.String(namespace), diff --git a/exporter/awsxrayexporter/translator/segment_test.go b/exporter/awsxrayexporter/translator/segment_test.go index fbdd34a845a8..0d9a97f0379e 100644 --- a/exporter/awsxrayexporter/translator/segment_test.go +++ b/exporter/awsxrayexporter/translator/segment_test.go @@ -119,6 +119,35 @@ func TestServerSpanWithInternalServerError(t *testing.T) { assert.True(t, *segment.Fault) } +func TestServerSpanWithThrottle(t *testing.T) { + spanName := "/api/locations" + parentSpanID := newSegmentID() + errorMessage := "java.lang.NullPointerException" + userAgent := "PostmanRuntime/7.21.0" + enduser := "go.tester@example.com" + attributes := make(map[string]interface{}) + attributes[semconventions.AttributeHTTPMethod] = "POST" + attributes[semconventions.AttributeHTTPURL] = "https://api.example.org/api/locations" + attributes[semconventions.AttributeHTTPTarget] = "/api/locations" + attributes[semconventions.AttributeHTTPStatusCode] = 429 + attributes[semconventions.AttributeHTTPStatusText] = "java.lang.NullPointerException" + attributes[semconventions.AttributeHTTPUserAgent] = userAgent + attributes[semconventions.AttributeEnduserID] = enduser + resource := constructDefaultResource() + span := constructServerSpan(parentSpanID, spanName, pdata.StatusCodeError, errorMessage, attributes) + timeEvents := constructTimedEventsWithSentMessageEvent(span.StartTimestamp()) + timeEvents.CopyTo(span.Events()) + + segment, _ := MakeSegment(span, resource, nil, false) + + assert.NotNil(t, segment) + assert.NotNil(t, segment.Cause) + assert.Equal(t, "signup_aggregator", *segment.Name) + assert.False(t, *segment.Fault) + assert.True(t, *segment.Error) + assert.True(t, *segment.Throttle) +} + func TestServerSpanNoParentId(t *testing.T) { spanName := "/api/locations" parentSpanID := pdata.InvalidSpanID()