Skip to content

Commit

Permalink
Merge pull request #818 from ektabj/main
Browse files Browse the repository at this point in the history
Adding data base user attribute in EMF logs
  • Loading branch information
thpierce authored Jul 3, 2024
2 parents 5cc5861 + 6f63a07 commit d5ad8f5
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ protected void assertAwsSpanAttributes(
String path,
String dbSystem,
String dbOperation,
String dbUser,
String type,
String identifier) {
assertThat(resourceScopeSpans)
Expand All @@ -61,7 +62,7 @@ protected void assertAwsSpanAttributes(
assertThat(rss.getSpan().getKind()).isEqualTo(SPAN_KIND_CLIENT);
var attributesList = rss.getSpan().getAttributesList();
assertAwsAttributes(
attributesList, method, path, dbSystem, dbOperation, type, identifier);
attributesList, method, path, dbSystem, dbOperation, dbUser, type, identifier);
});
}

Expand All @@ -71,6 +72,7 @@ protected void assertAwsAttributes(
String endpoint,
String dbSystem,
String dbOperation,
String dbUser,
String type,
String identifier) {
var assertions =
Expand Down Expand Up @@ -98,6 +100,11 @@ protected void assertAwsAttributes(
.isEqualTo(AppSignalsConstants.AWS_REMOTE_OPERATION);
assertThat(attribute.getValue().getStringValue()).isEqualTo(dbOperation);
})
.satisfiesOnlyOnce(
attribute -> {
assertThat(attribute.getKey()).isEqualTo(AppSignalsConstants.AWS_REMOTE_DB_USER);
assertThat(attribute.getValue().getStringValue()).isEqualTo(dbUser);
})
.satisfiesOnlyOnce(
attribute -> {
assertThat(attribute.getKey()).isEqualTo(AppSignalsConstants.AWS_SPAN_KIND);
Expand Down Expand Up @@ -327,7 +334,7 @@ protected void assertSuccess(
assertThat(response.status().isSuccess()).isTrue();

var traces = mockCollectorClient.getTraces();
assertAwsSpanAttributes(traces, method, path, dbSystem, dbOperation, type, identifier);
assertAwsSpanAttributes(traces, method, path, dbSystem, dbOperation, dbUser, type, identifier);
assertSemanticConventionsSpanAttributes(
traces, otelStatusCode, dbSqlTable, dbSystem, dbOperation, dbUser, dbName, jdbcUrl);

Expand Down Expand Up @@ -385,7 +392,7 @@ protected void assertFault(
assertThat(response.status().isServerError()).isTrue();

var traces = mockCollectorClient.getTraces();
assertAwsSpanAttributes(traces, method, path, dbSystem, dbOperation, type, identifier);
assertAwsSpanAttributes(traces, method, path, dbSystem, dbOperation, dbUser, type, identifier);
assertSemanticConventionsSpanAttributes(
traces, otelStatusCode, dbSqlTable, dbSystem, dbOperation, dbUser, dbName, jdbcUrl);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,5 @@ public class AppSignalsConstants {
public static final String AWS_REMOTE_RESOURCE_TYPE = "aws.remote.resource.type";
public static final String AWS_REMOTE_RESOURCE_IDENTIFIER = "aws.remote.resource.identifier";
public static final String AWS_SPAN_KIND = "aws.span.kind";
public static final String AWS_REMOTE_DB_USER = "aws.remote.db.user";
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ private AwsAttributeKeys() {}
static final AttributeKey<String> AWS_REMOTE_RESOURCE_TYPE =
AttributeKey.stringKey("aws.remote.resource.type");

static final AttributeKey<String> AWS_REMOTE_DB_USER =
AttributeKey.stringKey("aws.remote.db.user");

static final AttributeKey<String> AWS_SDK_DESCENDANT =
AttributeKey.stringKey("aws.sdk.descendant");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static io.opentelemetry.semconv.SemanticAttributes.DB_OPERATION;
import static io.opentelemetry.semconv.SemanticAttributes.DB_STATEMENT;
import static io.opentelemetry.semconv.SemanticAttributes.DB_SYSTEM;
import static io.opentelemetry.semconv.SemanticAttributes.DB_USER;
import static io.opentelemetry.semconv.SemanticAttributes.FAAS_INVOKED_NAME;
import static io.opentelemetry.semconv.SemanticAttributes.FAAS_TRIGGER;
import static io.opentelemetry.semconv.SemanticAttributes.GRAPHQL_OPERATION_TYPE;
Expand All @@ -45,6 +46,7 @@
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LOCAL_SERVICE;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_QUEUE_NAME;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_QUEUE_URL;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_DB_USER;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_OPERATION;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_RESOURCE_IDENTIFIER;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_RESOURCE_TYPE;
Expand Down Expand Up @@ -151,6 +153,7 @@ private Attributes generateDependencyMetricAttributes(SpanData span, Resource re
setRemoteResourceTypeAndIdentifier(span, builder);
setSpanKindForDependency(span, builder);
setHttpStatus(span, builder);
setRemoteDbUser(span, builder);

return builder.build();
}
Expand Down Expand Up @@ -526,6 +529,12 @@ private static void setHttpStatus(SpanData span, AttributesBuilder builder) {
}
}

private static void setRemoteDbUser(SpanData span, AttributesBuilder builder) {
if (isDBSpan(span) && isKeyPresent(span, DB_USER)) {
builder.put(AWS_REMOTE_DB_USER, span.getAttributes().get(DB_USER));
}
}

/**
* Attempt to pull status code from spans produced by AWS SDK instrumentation (both v1 and v2).
* AWS SDK instrumentation does not populate http.status_code when non-200 status codes are
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_LOCAL_SERVICE;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_QUEUE_NAME;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_QUEUE_URL;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_DB_USER;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_OPERATION;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_RESOURCE_IDENTIFIER;
import static software.amazon.opentelemetry.javaagent.providers.AwsAttributeKeys.AWS_REMOTE_RESOURCE_TYPE;
Expand Down Expand Up @@ -1029,6 +1030,60 @@ private void validateHttpStatusForNonLocalRootWithThrowableForClient(
}
}

@Test
public void testDBUserAttribute() {
mockAttribute(DB_OPERATION, "db_operation");
mockAttribute(DB_USER, "db_user");
when(spanDataMock.getKind()).thenReturn(SpanKind.CLIENT);

Attributes actualAttributes =
GENERATOR.generateMetricAttributeMapFromSpan(spanDataMock, resource).get(DEPENDENCY_METRIC);
assertThat(actualAttributes.get(AWS_REMOTE_OPERATION)).isEqualTo("db_operation");
assertThat(actualAttributes.get(AWS_REMOTE_DB_USER)).isEqualTo("db_user");
}

@Test
public void testDBUserAttributeAbsent() {
mockAttribute(DB_SYSTEM, "db_system");
when(spanDataMock.getKind()).thenReturn(SpanKind.CLIENT);

Attributes actualAttributes =
GENERATOR.generateMetricAttributeMapFromSpan(spanDataMock, resource).get(DEPENDENCY_METRIC);
assertThat(actualAttributes.get(AWS_REMOTE_DB_USER)).isNull();
}

@Test
public void testDBUserAttributeWithDifferentValues() {
mockAttribute(DB_OPERATION, "db_operation");
mockAttribute(DB_USER, "non_db_user");
when(spanDataMock.getKind()).thenReturn(SpanKind.CLIENT);

Attributes actualAttributes =
GENERATOR.generateMetricAttributeMapFromSpan(spanDataMock, resource).get(DEPENDENCY_METRIC);
assertThat(actualAttributes.get(AWS_REMOTE_DB_USER)).isEqualTo("non_db_user");
}

@Test
public void testDBUserAttributeNotPresentInServiceMetricForServerSpan() {
mockAttribute(DB_USER, "db_user");
mockAttribute(DB_SYSTEM, "db_system");
when(spanDataMock.getKind()).thenReturn(SpanKind.SERVER);

Attributes actualAttributes =
GENERATOR.generateMetricAttributeMapFromSpan(spanDataMock, resource).get(SERVICE_METRIC);
assertThat(actualAttributes.get(AWS_REMOTE_DB_USER)).isNull();
}

@Test
public void testDbUserPresentAndIsDbSpanFalse() {
mockAttribute(DB_USER, "DB user");
when(spanDataMock.getKind()).thenReturn(SpanKind.CLIENT);

Attributes actualAttributes =
GENERATOR.generateMetricAttributeMapFromSpan(spanDataMock, resource).get(DEPENDENCY_METRIC);
assertThat(actualAttributes.get(AWS_REMOTE_DB_USER)).isNull();
}

@Test
public void testNormalizeRemoteServiceName_NoNormalization() {
String serviceName = "non aws service";
Expand Down

0 comments on commit d5ad8f5

Please sign in to comment.