Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .snyk
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ ignore:
SNYK-JAVA-IONETTY-1042268:
- '*':
reason: no available replacement
expires: 2021-10-31T00:00:00.000Z
expires: 2021-12-31T00:00:00.000Z
patch: {}
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ dependencies {
implementation("io.opentelemetry:opentelemetry-proto:1.6.0-alpha")

// kafka
implementation("org.apache.kafka:kafka-clients:2.6.0")
implementation("org.apache.kafka:kafka-clients:2.7.2")

// test
testImplementation("org.junit.jupiter:junit-jupiter:5.7.1")
testImplementation("org.mockito:mockito-core:3.8.0")
testImplementation("com.google.code.gson:gson:2.8.7")
testImplementation("com.google.code.gson:gson:2.8.9")
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@ dependencies {
// open telemetry proto
implementation("io.opentelemetry:opentelemetry-proto:1.6.0-alpha")

constraints {
implementation("org.glassfish.jersey.core:jersey-common:2.34") {
because("introduced by org.hypertrace.core.kafkastreams.framework:" +
"kafka-streams-framework@0.1.21 > io.confluent:kafka-streams-avro-serde@6.0.1 > " +
"io.confluent:kafka-schema-registry-client@6.0.1 > " +
"org.glassfish.jersey.core:jersey-common@2.30")
}
}

// test
testImplementation("org.junit.jupiter:junit-jupiter:5.7.1")
testImplementation("org.mockito:mockito-core:3.8.0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@ val generateLocalGoGrpcFiles = false

protobuf {
protoc {
artifact = "com.google.protobuf:protoc:3.15.7"
artifact = "com.google.protobuf:protoc:3.17.3"
}
plugins {
id("grpc_java") {
artifact = "io.grpc:protoc-gen-grpc-java:1.41.0"
artifact = "io.grpc:protoc-gen-grpc-java:1.42.0"
}

if (generateLocalGoGrpcFiles) {
Expand Down Expand Up @@ -63,7 +63,7 @@ sourceSets {
}

dependencies {
api("com.google.protobuf:protobuf-java-util:3.15.7")
api("com.google.protobuf:protobuf-java-util:3.17.3")

implementation("org.hypertrace.core.datamodel:data-model:0.1.20")
implementation(project(":span-normalizer:raw-span-constants"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ public class EnrichedSpanConstants {
public static final String HEAD_EVENT_ID = "head.event.id";
public static final String API_EXIT_CALLS_COUNT = "api.exit.calls.count";
public static final String UNIQUE_API_NODES_COUNT = "unique.apis.count";
public static final String GRPC_REQUEST_URL = "grpc.request.url";
public static final String GRPC_REQUEST_ENDPOINT = "grpc.request.endpoint";

/**
* Returns the constant value for the given Enum.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ dependencies {
implementation("org.hypertrace.core.datamodel:data-model:0.1.20")
implementation("org.hypertrace.entity.service:entity-service-client:0.8.5")
implementation("org.hypertrace.core.serviceframework:platform-metrics:0.1.28")
implementation("org.hypertrace.core.grpcutils:grpc-client-utils:0.6.1")
implementation("org.hypertrace.core.grpcutils:grpc-client-utils:0.6.2")
implementation("org.hypertrace.config.service:spaces-config-service-api:0.1.0")
implementation("org.hypertrace.core.grpcutils:grpc-context-utils:0.6.1")
implementation("org.hypertrace.core.grpcutils:grpc-context-utils:0.6.2")

implementation("com.typesafe:config:1.4.1")
implementation("org.apache.httpcomponents:httpclient:4.5.13")
Expand All @@ -33,5 +33,5 @@ dependencies {
testImplementation("org.junit.jupiter:junit-jupiter:5.7.1")
testImplementation("org.mockito:mockito-core:3.8.0")
testImplementation("org.mockito:mockito-junit-jupiter:3.8.0")
testImplementation("io.grpc:grpc-core:1.41.0")
testImplementation("io.grpc:grpc-core:1.42.0")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package org.hypertrace.traceenricher.enrichment.enrichers;

import static org.hypertrace.traceenricher.enrichedspan.constants.EnrichedSpanConstants.GRPC_REQUEST_ENDPOINT;
import static org.hypertrace.traceenricher.enrichedspan.constants.EnrichedSpanConstants.GRPC_REQUEST_URL;

import java.util.Optional;
import org.hypertrace.core.datamodel.Event;
import org.hypertrace.core.datamodel.StructuredTrace;
import org.hypertrace.core.datamodel.shared.trace.AttributeValueCreator;
import org.hypertrace.semantic.convention.utils.rpc.RpcSemanticConventionUtils;
import org.hypertrace.traceenricher.enrichedspan.constants.utils.EnrichedSpanUtils;
import org.hypertrace.traceenricher.enrichedspan.constants.v1.Protocol;
import org.hypertrace.traceenricher.enrichment.AbstractTraceEnricher;

public class GrpcAttributeEnricher extends AbstractTraceEnricher {

private static final String GRPC_RECV_DOT = "Recv.";
private static final String GRPC_SENT_DOT = "Sent.";

@Override
public void enrichEvent(StructuredTrace trace, Event event) {
// if protocol is Grpc update attribute
Protocol protocol = EnrichedSpanUtils.getProtocol(event);
if (Protocol.PROTOCOL_GRPC == protocol) {
Optional<String> grpcRequestEndpoint =
RpcSemanticConventionUtils.getGrpcRequestEndpoint(event);
if (grpcRequestEndpoint.isPresent()) {
addEnrichedAttribute(
event, GRPC_REQUEST_ENDPOINT, AttributeValueCreator.create(grpcRequestEndpoint.get()));

String prefix = getPrefix(event);
addEnrichedAttribute(
event,
GRPC_REQUEST_URL,
AttributeValueCreator.create(prefix.concat(grpcRequestEndpoint.get())));
}
}
}

private String getPrefix(Event event) {
if (EnrichedSpanUtils.isEntrySpan(event)) {
return GRPC_RECV_DOT;
} else if (EnrichedSpanUtils.isExitSpan(event)) {
return GRPC_SENT_DOT;
}
return "";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package org.hypertrace.traceenricher.enrichment.enrichers;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.Mockito.when;

import org.hypertrace.core.datamodel.AttributeValue;
import org.hypertrace.core.datamodel.Event;
import org.hypertrace.core.datamodel.StructuredTrace;
import org.hypertrace.core.datamodel.shared.SpanAttributeUtils;
import org.hypertrace.traceenricher.enrichedspan.constants.EnrichedSpanConstants;
import org.hypertrace.traceenricher.enrichedspan.constants.v1.CommonAttribute;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;

public class GrpcAttributeEnricherTest extends AbstractAttributeEnricherTest {

@Mock private StructuredTrace mockTrace;

private final GrpcAttributeEnricher enricher = new GrpcAttributeEnricher();

/*
* Covers cases of GrpcAttributeEnricher, the details cases of getGrpcRequestEndpoint
* are covered at RpcSemanticConventionUtilsTest
* */
@Test
public void test_withAValidUrl_shouldEnrichHttpPathAndParams() {
// case 1: using event name prefixed with Recv
Event e = createMockEvent();
when(e.getEventName()).thenReturn("Recv.TestService.GetEventEchos");
addAttribute(
e, EnrichedSpanConstants.getValue(CommonAttribute.COMMON_ATTRIBUTE_PROTOCOL), "GRPC");
addAttribute(
e, EnrichedSpanConstants.getValue(CommonAttribute.COMMON_ATTRIBUTE_SPAN_TYPE), "ENTRY");

enricher.enrichEvent(mockTrace, e);

String grpcRequestUrl =
SpanAttributeUtils.getStringAttribute(e, EnrichedSpanConstants.GRPC_REQUEST_URL);
assertEquals("Recv.TestService.GetEventEchos", grpcRequestUrl);

String grpcRequestEndPoint =
SpanAttributeUtils.getStringAttribute(e, EnrichedSpanConstants.GRPC_REQUEST_ENDPOINT);
assertEquals("TestService.GetEventEchos", grpcRequestEndPoint);

// case 2: using grpc.path
e = createMockEvent();
when(e.getEventName()).thenReturn("TestService.GetEventEchos");
addAttribute(
e, EnrichedSpanConstants.getValue(CommonAttribute.COMMON_ATTRIBUTE_PROTOCOL), "GRPC");
addAttribute(
e, EnrichedSpanConstants.getValue(CommonAttribute.COMMON_ATTRIBUTE_SPAN_TYPE), "ENTRY");
addAttribute(e, "grpc.path", "/TestGrpcService/GetGrpcPathEchos");

enricher.enrichEvent(mockTrace, e);

grpcRequestUrl =
SpanAttributeUtils.getStringAttribute(e, EnrichedSpanConstants.GRPC_REQUEST_URL);
assertEquals("Recv.TestGrpcService.GetGrpcPathEchos", grpcRequestUrl);

grpcRequestEndPoint =
SpanAttributeUtils.getStringAttribute(e, EnrichedSpanConstants.GRPC_REQUEST_ENDPOINT);
assertEquals("TestGrpcService.GetGrpcPathEchos", grpcRequestEndPoint);

// case 3: no grpc protocol
e = createMockEvent();
when(e.getEventName()).thenReturn("TestService.GetEventEchos");
addAttribute(
e, EnrichedSpanConstants.getValue(CommonAttribute.COMMON_ATTRIBUTE_SPAN_TYPE), "ENTRY");
addAttribute(e, "grpc.path", "/TestGrpcService/GetGrpcPathEchos");

enricher.enrichEvent(mockTrace, e);

grpcRequestUrl =
SpanAttributeUtils.getStringAttribute(e, EnrichedSpanConstants.GRPC_REQUEST_URL);
assertNull(grpcRequestUrl);

grpcRequestEndPoint =
SpanAttributeUtils.getStringAttribute(e, EnrichedSpanConstants.GRPC_REQUEST_ENDPOINT);
assertNull(grpcRequestEndPoint);

// case 4: client call - EXIT
e = createMockEvent();
when(e.getEventName()).thenReturn("TestService.GetEventEchos");
addAttribute(
e, EnrichedSpanConstants.getValue(CommonAttribute.COMMON_ATTRIBUTE_PROTOCOL), "GRPC");
addAttribute(
e, EnrichedSpanConstants.getValue(CommonAttribute.COMMON_ATTRIBUTE_SPAN_TYPE), "EXIT");
addAttribute(e, "grpc.path", "/TestGrpcService/GetGrpcPathEchos");

enricher.enrichEvent(mockTrace, e);

grpcRequestUrl =
SpanAttributeUtils.getStringAttribute(e, EnrichedSpanConstants.GRPC_REQUEST_URL);
assertEquals("Sent.TestGrpcService.GetGrpcPathEchos", grpcRequestUrl);

grpcRequestEndPoint =
SpanAttributeUtils.getStringAttribute(e, EnrichedSpanConstants.GRPC_REQUEST_ENDPOINT);
assertEquals("TestGrpcService.GetGrpcPathEchos", grpcRequestEndPoint);

// case 5: no entry or exsit span (internal span) - not prefix sent / recv
e = createMockEvent();
when(e.getEventName()).thenReturn("TestService.GetEventEchos");
addAttribute(
e, EnrichedSpanConstants.getValue(CommonAttribute.COMMON_ATTRIBUTE_PROTOCOL), "GRPC");
addAttribute(e, "grpc.path", "/TestGrpcService/GetGrpcPathEchos");

enricher.enrichEvent(mockTrace, e);

grpcRequestUrl =
SpanAttributeUtils.getStringAttribute(e, EnrichedSpanConstants.GRPC_REQUEST_URL);
assertEquals("TestGrpcService.GetGrpcPathEchos", grpcRequestUrl);

grpcRequestEndPoint =
SpanAttributeUtils.getStringAttribute(e, EnrichedSpanConstants.GRPC_REQUEST_ENDPOINT);
assertEquals("TestGrpcService.GetGrpcPathEchos", grpcRequestEndPoint);
}

private void addAttribute(Event event, String key, String val) {
event
.getAttributes()
.getAttributeMap()
.put(key, AttributeValue.newBuilder().setValue(val).build());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,9 @@ enricher {
port = 50061
}
}

GrpcAttributeEnricher {
class = "org.hypertrace.traceenricher.enrichment.enrichers.GrpcAttributeEnricher"
dependencies = ["SpanTypeAttributeEnricher", "ApiBoundaryTypeAttributeEnricher"]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ dependencies {
}

// Required for the GRPC clients.
runtimeOnly("io.grpc:grpc-netty:1.41.0")
runtimeOnly("io.grpc:grpc-netty:1.42.0")

// Logging
implementation("org.slf4j:slf4j-api:1.7.30")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ kafka.streams.config = {
}

enricher {
names = ["SpanTypeAttributeEnricher", "ApiStatusEnricher", "EndpointEnricher", "TransactionNameEnricher", "ApiBoundaryTypeAttributeEnricher", "ErrorsAndExceptionsEnricher", "BackendEntityEnricher", "HttpAttributeEnricher", "DefaultServiceEntityEnricher", "UserAgentSpanEnricher", "SpaceEnricher", "EntitySpanEnricher", "ExitCallsEnricher", "TraceStatsEnricher"]
names = ["SpanTypeAttributeEnricher", "ApiStatusEnricher", "EndpointEnricher", "TransactionNameEnricher", "ApiBoundaryTypeAttributeEnricher", "ErrorsAndExceptionsEnricher", "BackendEntityEnricher", "HttpAttributeEnricher", "DefaultServiceEntityEnricher", "UserAgentSpanEnricher", "SpaceEnricher", "EntitySpanEnricher", "ExitCallsEnricher", "TraceStatsEnricher", "GrpcAttributeEnricher"]

clients = {
entity.service.config = {
Expand Down Expand Up @@ -110,6 +110,11 @@ enricher {
class = "org.hypertrace.traceenricher.enrichment.enrichers.TraceStatsEnrichere"
dependencies = ["EndpointEnricher"]
}

GrpcAttributeEnricher {
class = "org.hypertrace.traceenricher.enrichment.enrichers.GrpcAttributeEnricher"
dependencies = ["SpanTypeAttributeEnricher", "ApiBoundaryTypeAttributeEnricher"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is PROTOCOL and enriched attribute?
If yes, are these 2 dependencies good enough for that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes PROTOCOL is enriched attributes, and these deps take care of both enriched attributes required by this enricher.
Ref :

}
}

logger {
Expand Down
4 changes: 2 additions & 2 deletions hypertrace-trace-enricher/trace-reader/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ dependencies {
api("org.hypertrace.entity.service:entity-data-service-rx-client:0.8.5")
api("org.hypertrace.core.datamodel:data-model:0.1.20")
implementation("org.hypertrace.core.attribute.service:attribute-projection-registry:0.12.3")
implementation("org.hypertrace.core.grpcutils:grpc-client-rx-utils:0.6.1")
implementation("org.hypertrace.core.grpcutils:grpc-context-utils:0.6.1")
implementation("org.hypertrace.core.grpcutils:grpc-client-rx-utils:0.6.2")
implementation("org.hypertrace.core.grpcutils:grpc-context-utils:0.6.2")
implementation("io.reactivex.rxjava3:rxjava:3.0.11")

annotationProcessor("org.projectlombok:lombok:1.18.20")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,5 @@ dependencies {

testImplementation("org.junit.jupiter:junit-jupiter:5.7.1")
testImplementation("org.mockito:mockito-core:3.8.0")
testImplementation("com.google.code.gson:gson:2.8.7")
testImplementation("com.google.code.gson:gson:2.8.9")
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.avro.Schema;
import org.hypertrace.core.datamodel.Entity;
Expand All @@ -15,7 +16,6 @@
import org.hypertrace.core.datamodel.StructuredTrace;
import org.hypertrace.core.datamodel.shared.SpanAttributeUtils;
import org.hypertrace.semantic.convention.utils.http.HttpSemanticConventionUtils;
import org.hypertrace.semantic.convention.utils.rpc.RpcSemanticConventionUtils;
import org.hypertrace.traceenricher.enrichedspan.constants.EnrichedSpanConstants;
import org.hypertrace.traceenricher.enrichedspan.constants.utils.EnrichedSpanUtils;
import org.hypertrace.traceenricher.enrichedspan.constants.v1.Api;
Expand Down Expand Up @@ -318,15 +318,10 @@ String getRequestUrl(Event event, Protocol protocol) {
.orElse(HttpSemanticConventionUtils.getHttpPath(event).orElse(null));

case PROTOCOL_GRPC:
/**
* For RPC methods, we show URL/URI as a combination of rpc.service and rpc.method. The same
* information is also available as Span Name -
* https://github.com/open-telemetry/opentelemetry-specification/blob/3e380e249f60c3a5f68746f5e84d10195ba41a79/specification/trace/semantic_conventions/rpc.md#span-name
* So, as part of this method, we will form Url using rpc.service and rpc.method, and
* fallback to spanName. While setting GRPC protocol from rpc attributes, it already checks
* for rpc.system.
*/
return RpcSemanticConventionUtils.getRpcPath(event).orElse(event.getEventName());
return Optional.ofNullable(
SpanAttributeUtils.getStringAttribute(
event, EnrichedSpanConstants.GRPC_REQUEST_URL))
.orElse(event.getEventName());
}
return null;
}
Expand Down
Loading