From b8707f91a7cc03025ab46052700cb5fb3a777115 Mon Sep 17 00:00:00 2001 From: rish691 Date: Thu, 29 Apr 2021 00:20:32 +0530 Subject: [PATCH 1/4] Add spanId attribute for span-log join query --- .../graphql/span/dao/SpanLogEventDao.java | 6 +- .../span/dao/SpanLogEventRequestBuilder.java | 73 +++++++++++++++---- .../dao/SpanLogEventResponseConverter.java | 27 ++++++- .../dao/SpanLogEventRequestBuilderTest.java | 69 +++++++++++++++++- 4 files changed, 153 insertions(+), 22 deletions(-) diff --git a/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventDao.java b/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventDao.java index ff9b168d..953e87d6 100644 --- a/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventDao.java +++ b/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventDao.java @@ -5,6 +5,7 @@ import io.reactivex.rxjava3.core.Single; import java.util.Map; import javax.inject.Inject; +import org.hypertrace.core.graphql.attributes.AttributeStore; import org.hypertrace.core.graphql.context.GraphQlRequestContext; import org.hypertrace.core.graphql.span.request.SpanRequest; import org.hypertrace.core.graphql.utils.grpc.GraphQlGrpcContextBuilder; @@ -21,17 +22,20 @@ class SpanLogEventDao { private final GraphQlGrpcContextBuilder grpcContextBuilder; private final SpanLogEventRequestBuilder spanLogEventRequestBuilder; private final SpanLogEventResponseConverter spanLogEventResponseConverter; + private final AttributeStore attributeStore; @Inject SpanLogEventDao( GatewayServiceFutureStub gatewayServiceFutureStub, GraphQlGrpcContextBuilder grpcContextBuilder, SpanLogEventRequestBuilder spanLogEventRequestBuilder, - SpanLogEventResponseConverter spanLogEventResponseConverter) { + SpanLogEventResponseConverter spanLogEventResponseConverter, + AttributeStore attributeStore) { this.gatewayServiceStub = gatewayServiceFutureStub; this.grpcContextBuilder = grpcContextBuilder; this.spanLogEventRequestBuilder = spanLogEventRequestBuilder; this.spanLogEventResponseConverter = spanLogEventResponseConverter; + this.attributeStore = attributeStore; } /** diff --git a/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilder.java b/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilder.java index 46d1d4f1..0ceddcf8 100644 --- a/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilder.java +++ b/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilder.java @@ -3,12 +3,15 @@ import static io.reactivex.rxjava3.core.Single.zip; import io.reactivex.rxjava3.core.Single; +import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import javax.inject.Inject; import lombok.experimental.Accessors; +import org.hypertrace.core.graphql.attributes.AttributeModel; +import org.hypertrace.core.graphql.attributes.AttributeStore; import org.hypertrace.core.graphql.atttributes.scopes.HypertraceCoreAttributeScopeString; import org.hypertrace.core.graphql.common.request.AttributeAssociation; import org.hypertrace.core.graphql.common.request.AttributeRequest; @@ -18,6 +21,7 @@ import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterOperatorType; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterType; import org.hypertrace.core.graphql.common.utils.Converter; +import org.hypertrace.core.graphql.context.GraphQlRequestContext; import org.hypertrace.core.graphql.span.request.SpanRequest; import org.hypertrace.gateway.service.v1.common.Expression; import org.hypertrace.gateway.service.v1.common.Filter; @@ -29,31 +33,67 @@ class SpanLogEventRequestBuilder { private final Converter, Set> attributeConverter; private final Converter>, Filter> filterConverter; private final FilterRequestBuilder filterRequestBuilder; + private final AttributeStore attributeStore; @Inject SpanLogEventRequestBuilder( Converter, Set> attributeConverter, Converter>, Filter> filterConverter, - FilterRequestBuilder filterRequestBuilder) { + FilterRequestBuilder filterRequestBuilder, + AttributeStore attributeStore) { this.attributeConverter = attributeConverter; this.filterConverter = filterConverter; this.filterRequestBuilder = filterRequestBuilder; + this.attributeStore = attributeStore; } Single buildLogEventsRequest( SpanRequest gqlRequest, SpansResponse spansResponse) { - return zip( - this.attributeConverter.convert(gqlRequest.logEventAttributes()), - buildLogEventsQueryFilter(gqlRequest, spansResponse).flatMap(filterConverter::convert), - (selections, filter) -> - LogEventsRequest.newBuilder() - .setStartTimeMillis( - gqlRequest.spanEventsRequest().timeRange().startTime().toEpochMilli()) - .setEndTimeMillis( - gqlRequest.spanEventsRequest().timeRange().endTime().toEpochMilli()) - .addAllSelection(selections) - .setFilter(filter) - .build()); + return getRequestAttributes( + gqlRequest.spanEventsRequest().context(), gqlRequest.logEventAttributes()) + .flatMap( + v -> + zip( + this.attributeConverter.convert(v), + buildLogEventsQueryFilter(gqlRequest, spansResponse) + .flatMap(filterConverter::convert), + (selections, filter) -> + LogEventsRequest.newBuilder() + .setStartTimeMillis( + gqlRequest + .spanEventsRequest() + .timeRange() + .startTime() + .toEpochMilli()) + .setEndTimeMillis( + gqlRequest.spanEventsRequest().timeRange().endTime().toEpochMilli()) + .addAllSelection(selections) + .setFilter(filter) + .build())); + } + + private Single> getRequestAttributes( + GraphQlRequestContext requestContext, Collection logEventAttributes) { + return this.attributeStore + .getForeignIdAttribute( + requestContext, + HypertraceCoreAttributeScopeString.LOG_EVENT, + HypertraceCoreAttributeScopeString.SPAN) + .flatMap( + spanId -> + logEventAttributes.stream() + .anyMatch( + logEventAttribute -> + logEventAttribute.attribute().key().equals(spanId.key())) + ? Single.just(logEventAttributes) + : get(spanId, logEventAttributes)); + } + + private Single> get( + AttributeModel attributeModel, Collection requests) { + List list = new ArrayList<>(requests); + list.add(new DefaultAttributeRequest(attributeModel, "")); + return Single.just(list); } private Single>> buildLogEventsQueryFilter( @@ -85,4 +125,11 @@ private static class LogEventFilter implements FilterArgument { AttributeScope idType = null; String idScope = HypertraceCoreAttributeScopeString.SPAN; } + + @lombok.Value + @Accessors(fluent = true) + class DefaultAttributeRequest implements AttributeRequest { + AttributeModel attribute; + String alias; + } } diff --git a/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventResponseConverter.java b/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventResponseConverter.java index 5b9a59ce..5ce19b09 100644 --- a/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventResponseConverter.java +++ b/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventResponseConverter.java @@ -54,18 +54,37 @@ private Single buildResponse( LogEventsResponse logEventsResponse) { return Observable.fromIterable(logEventsResponse.getLogEventsList()) .concatMapSingle( - logEventsResponseVar -> this.convert(attributeRequests, logEventsResponseVar)) - .collect(Collectors.groupingBy(logEvent -> (String) logEvent.attribute(foreignIdAttribute))) + logEventsResponseVar -> + this.convert(foreignIdAttribute, attributeRequests, logEventsResponseVar)) + .collect( + Collectors.groupingBy( + spanLogEventPair -> spanLogEventPair.spanId, + Collectors.mapping(v -> v.logEvent, Collectors.toList()))) .map( spanIdVsLogEventsMap -> new SpanLogEventsResponse(spansResponse, spanIdVsLogEventsMap)); } - private Single convert( + private Single convert( + String foreignIdAttribute, Collection request, org.hypertrace.gateway.service.v1.log.events.LogEvent logEvent) { return this.attributeMapConverter .convert(request, logEvent.getAttributesMap()) - .map(ConvertedLogEvent::new); + .map( + attributeMap -> + new SpanLogEventPair( + logEvent.getAttributesMap().get(foreignIdAttribute).getString(), + new ConvertedLogEvent(attributeMap))); + } + + static class SpanLogEventPair { + String spanId; + LogEvent logEvent; + + SpanLogEventPair(String spanId, LogEvent logEvent) { + this.spanId = spanId; + this.logEvent = logEvent; + } } @lombok.Value diff --git a/hypertrace-core-graphql-span-schema/src/test/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilderTest.java b/hypertrace-core-graphql-span-schema/src/test/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilderTest.java index 3e1db88a..dde54524 100644 --- a/hypertrace-core-graphql-span-schema/src/test/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilderTest.java +++ b/hypertrace-core-graphql-span-schema/src/test/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilderTest.java @@ -7,8 +7,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyCollection; +import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import com.google.inject.AbstractModule; import com.google.inject.Guice; @@ -25,6 +27,7 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import org.hypertrace.core.graphql.attributes.AttributeStore; import org.hypertrace.core.graphql.common.request.AttributeAssociation; import org.hypertrace.core.graphql.common.request.AttributeRequest; import org.hypertrace.core.graphql.common.request.FilterRequestBuilder; @@ -54,6 +57,8 @@ class SpanLogEventRequestBuilderTest { @Mock private FilterRequestBuilder filterRequestBuilder; + @Mock AttributeStore attributeStore; + private SpanLogEventRequestBuilder spanLogEventRequestBuilder; @BeforeEach @@ -82,11 +87,9 @@ protected void configure() { new TypeLiteral, Set>>() {})); spanLogEventRequestBuilder = - new SpanLogEventRequestBuilder(attributeConverter, filterConverter, filterRequestBuilder); - } + new SpanLogEventRequestBuilder( + attributeConverter, filterConverter, filterRequestBuilder, attributeStore); - @Test - void testBuildRequest() { doAnswer( invocation -> { Set filterArguments = invocation.getArgument(2, Set.class); @@ -103,6 +106,13 @@ void testBuildRequest() { .when(filterRequestBuilder) .build(any(), any(), anyCollection()); + when(attributeStore.getForeignIdAttribute(any(), anyString(), anyString())) + .thenReturn(Single.just(spanIdAttribute.attribute())); + } + + @Test + void testBuildRequest() { + long startTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis() + Duration.ofHours(1).toMillis(); @@ -152,4 +162,55 @@ void testBuildRequest() { .map(v -> v.getColumnIdentifier().getColumnName()) .collect(Collectors.toSet())); } + + @Test + void testBuildRequest_addSpanId() { + long startTime = System.currentTimeMillis(); + long endTime = System.currentTimeMillis() + Duration.ofHours(1).toMillis(); + + Collection logAttributeRequests = List.of(traceIdAttribute); + ResultSetRequest resultSetRequest = + new DefaultResultSetRequest( + null, + List.of(DaoTestUtil.eventIdAttribute), + new DefaultTimeRange(Instant.ofEpochMilli(startTime), Instant.ofEpochMilli(endTime)), + DaoTestUtil.eventIdAttribute, + 0, + 0, + List.of(), + Collections.emptyList(), + Optional.empty()); + SpanRequest spanRequest = new DefaultSpanRequest(resultSetRequest, logAttributeRequests); + + LogEventsRequest logEventsRequest = + spanLogEventRequestBuilder.buildLogEventsRequest(spanRequest, spansResponse).blockingGet(); + + assertEquals(Operator.IN, logEventsRequest.getFilter().getChildFilter(0).getOperator()); + assertEquals( + spanIdAttribute.attribute().id(), + logEventsRequest + .getFilter() + .getChildFilter(0) + .getLhs() + .getColumnIdentifier() + .getColumnName()); + assertEquals( + List.of("span1", "span2", "span3"), + logEventsRequest + .getFilter() + .getChildFilter(0) + .getRhs() + .getLiteral() + .getValue() + .getStringArrayList() + .stream() + .collect(Collectors.toList())); + assertEquals(startTime, logEventsRequest.getStartTimeMillis()); + assertEquals(endTime, logEventsRequest.getEndTimeMillis()); + assertEquals( + Set.of("traceId", "spanId"), + logEventsRequest.getSelectionList().stream() + .map(v -> v.getColumnIdentifier().getColumnName()) + .collect(Collectors.toSet())); + } } From ee81427fe53093c08906719b39b74d4f91fc96fd Mon Sep 17 00:00:00 2001 From: rish691 Date: Thu, 29 Apr 2021 00:22:39 +0530 Subject: [PATCH 2/4] . --- .../hypertrace/core/graphql/span/dao/SpanLogEventDao.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventDao.java b/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventDao.java index 953e87d6..ff9b168d 100644 --- a/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventDao.java +++ b/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventDao.java @@ -5,7 +5,6 @@ import io.reactivex.rxjava3.core.Single; import java.util.Map; import javax.inject.Inject; -import org.hypertrace.core.graphql.attributes.AttributeStore; import org.hypertrace.core.graphql.context.GraphQlRequestContext; import org.hypertrace.core.graphql.span.request.SpanRequest; import org.hypertrace.core.graphql.utils.grpc.GraphQlGrpcContextBuilder; @@ -22,20 +21,17 @@ class SpanLogEventDao { private final GraphQlGrpcContextBuilder grpcContextBuilder; private final SpanLogEventRequestBuilder spanLogEventRequestBuilder; private final SpanLogEventResponseConverter spanLogEventResponseConverter; - private final AttributeStore attributeStore; @Inject SpanLogEventDao( GatewayServiceFutureStub gatewayServiceFutureStub, GraphQlGrpcContextBuilder grpcContextBuilder, SpanLogEventRequestBuilder spanLogEventRequestBuilder, - SpanLogEventResponseConverter spanLogEventResponseConverter, - AttributeStore attributeStore) { + SpanLogEventResponseConverter spanLogEventResponseConverter) { this.gatewayServiceStub = gatewayServiceFutureStub; this.grpcContextBuilder = grpcContextBuilder; this.spanLogEventRequestBuilder = spanLogEventRequestBuilder; this.spanLogEventResponseConverter = spanLogEventResponseConverter; - this.attributeStore = attributeStore; } /** From 832f0fde748c14744a4e54f12caa5380c5587e1b Mon Sep 17 00:00:00 2001 From: rish691 Date: Thu, 29 Apr 2021 00:25:58 +0530 Subject: [PATCH 3/4] . --- .../core/graphql/span/dao/SpanLogEventRequestBuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilder.java b/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilder.java index 0ceddcf8..a87b5113 100644 --- a/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilder.java +++ b/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilder.java @@ -86,10 +86,10 @@ private Single> getRequestAttributes( logEventAttribute -> logEventAttribute.attribute().key().equals(spanId.key())) ? Single.just(logEventAttributes) - : get(spanId, logEventAttributes)); + : updateRequestAttribute(spanId, logEventAttributes)); } - private Single> get( + private Single> updateRequestAttribute( AttributeModel attributeModel, Collection requests) { List list = new ArrayList<>(requests); list.add(new DefaultAttributeRequest(attributeModel, "")); From 26cde209ae160703ac0e011b62cc8c12f2e6378e Mon Sep 17 00:00:00 2001 From: rish691 Date: Thu, 29 Apr 2021 13:37:16 +0530 Subject: [PATCH 4/4] review comment --- .../span/dao/SpanLogEventRequestBuilder.java | 72 +++++++------------ .../dao/SpanLogEventResponseConverter.java | 23 +++--- .../dao/SpanLogEventRequestBuilderTest.java | 25 +++++-- .../SpanLogEventResponseConverterTest.java | 32 ++++++++- 4 files changed, 87 insertions(+), 65 deletions(-) diff --git a/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilder.java b/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilder.java index a87b5113..1e021e53 100644 --- a/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilder.java +++ b/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilder.java @@ -2,19 +2,19 @@ import static io.reactivex.rxjava3.core.Single.zip; +import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Single; -import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Set; import java.util.stream.Collectors; import javax.inject.Inject; import lombok.experimental.Accessors; -import org.hypertrace.core.graphql.attributes.AttributeModel; import org.hypertrace.core.graphql.attributes.AttributeStore; import org.hypertrace.core.graphql.atttributes.scopes.HypertraceCoreAttributeScopeString; import org.hypertrace.core.graphql.common.request.AttributeAssociation; import org.hypertrace.core.graphql.common.request.AttributeRequest; +import org.hypertrace.core.graphql.common.request.AttributeRequestBuilder; import org.hypertrace.core.graphql.common.request.FilterRequestBuilder; import org.hypertrace.core.graphql.common.schema.attributes.AttributeScope; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterArgument; @@ -34,66 +34,51 @@ class SpanLogEventRequestBuilder { private final Converter>, Filter> filterConverter; private final FilterRequestBuilder filterRequestBuilder; private final AttributeStore attributeStore; + private final AttributeRequestBuilder attributeRequestBuilder; @Inject SpanLogEventRequestBuilder( Converter, Set> attributeConverter, Converter>, Filter> filterConverter, FilterRequestBuilder filterRequestBuilder, - AttributeStore attributeStore) { + AttributeStore attributeStore, + AttributeRequestBuilder attributeRequestBuilder) { this.attributeConverter = attributeConverter; this.filterConverter = filterConverter; this.filterRequestBuilder = filterRequestBuilder; this.attributeStore = attributeStore; + this.attributeRequestBuilder = attributeRequestBuilder; } Single buildLogEventsRequest( SpanRequest gqlRequest, SpansResponse spansResponse) { - return getRequestAttributes( - gqlRequest.spanEventsRequest().context(), gqlRequest.logEventAttributes()) - .flatMap( - v -> - zip( - this.attributeConverter.convert(v), - buildLogEventsQueryFilter(gqlRequest, spansResponse) - .flatMap(filterConverter::convert), - (selections, filter) -> - LogEventsRequest.newBuilder() - .setStartTimeMillis( - gqlRequest - .spanEventsRequest() - .timeRange() - .startTime() - .toEpochMilli()) - .setEndTimeMillis( - gqlRequest.spanEventsRequest().timeRange().endTime().toEpochMilli()) - .addAllSelection(selections) - .setFilter(filter) - .build())); + return zip( + getRequestAttributes( + gqlRequest.spanEventsRequest().context(), gqlRequest.logEventAttributes()), + buildLogEventsQueryFilter(gqlRequest, spansResponse).flatMap(filterConverter::convert), + (selections, filter) -> + LogEventsRequest.newBuilder() + .setStartTimeMillis( + gqlRequest.spanEventsRequest().timeRange().startTime().toEpochMilli()) + .setEndTimeMillis( + gqlRequest.spanEventsRequest().timeRange().endTime().toEpochMilli()) + .addAllSelection(selections) + .setFilter(filter) + .build()); } - private Single> getRequestAttributes( + private Single> getRequestAttributes( GraphQlRequestContext requestContext, Collection logEventAttributes) { return this.attributeStore .getForeignIdAttribute( requestContext, HypertraceCoreAttributeScopeString.LOG_EVENT, HypertraceCoreAttributeScopeString.SPAN) - .flatMap( - spanId -> - logEventAttributes.stream() - .anyMatch( - logEventAttribute -> - logEventAttribute.attribute().key().equals(spanId.key())) - ? Single.just(logEventAttributes) - : updateRequestAttribute(spanId, logEventAttributes)); - } - - private Single> updateRequestAttribute( - AttributeModel attributeModel, Collection requests) { - List list = new ArrayList<>(requests); - list.add(new DefaultAttributeRequest(attributeModel, "")); - return Single.just(list); + .map(attributeRequestBuilder::buildForAttribute) + .toObservable() + .mergeWith(Observable.fromIterable(logEventAttributes)) + .collect(Collectors.toSet()) + .flatMap(attributeConverter::convert); } private Single>> buildLogEventsQueryFilter( @@ -125,11 +110,4 @@ private static class LogEventFilter implements FilterArgument { AttributeScope idType = null; String idScope = HypertraceCoreAttributeScopeString.SPAN; } - - @lombok.Value - @Accessors(fluent = true) - class DefaultAttributeRequest implements AttributeRequest { - AttributeModel attribute; - String alias; - } } diff --git a/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventResponseConverter.java b/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventResponseConverter.java index 5ce19b09..938c84df 100644 --- a/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventResponseConverter.java +++ b/hypertrace-core-graphql-span-schema/src/main/java/org/hypertrace/core/graphql/span/dao/SpanLogEventResponseConverter.java @@ -7,6 +7,7 @@ import java.util.stream.Collectors; import javax.inject.Inject; import lombok.experimental.Accessors; +import org.hypertrace.core.graphql.attributes.AttributeModel; import org.hypertrace.core.graphql.attributes.AttributeStore; import org.hypertrace.core.graphql.atttributes.scopes.HypertraceCoreAttributeScopeString; import org.hypertrace.core.graphql.common.request.AttributeRequest; @@ -43,12 +44,11 @@ Single buildResponse( HypertraceCoreAttributeScopeString.LOG_EVENT, HypertraceCoreAttributeScopeString.SPAN) .flatMap( - spanId -> - buildResponse(spanId.key(), attributeRequests, spansResponse, logEventsResponse)); + spanId -> buildResponse(spanId, attributeRequests, spansResponse, logEventsResponse)); } private Single buildResponse( - String foreignIdAttribute, + AttributeModel foreignIdAttribute, Collection attributeRequests, SpansResponse spansResponse, LogEventsResponse logEventsResponse) { @@ -58,14 +58,14 @@ private Single buildResponse( this.convert(foreignIdAttribute, attributeRequests, logEventsResponseVar)) .collect( Collectors.groupingBy( - spanLogEventPair -> spanLogEventPair.spanId, - Collectors.mapping(v -> v.logEvent, Collectors.toList()))) + SpanLogEventPair::spanId, + Collectors.mapping(SpanLogEventPair::logEvent, Collectors.toList()))) .map( spanIdVsLogEventsMap -> new SpanLogEventsResponse(spansResponse, spanIdVsLogEventsMap)); } private Single convert( - String foreignIdAttribute, + AttributeModel foreignIdAttribute, Collection request, org.hypertrace.gateway.service.v1.log.events.LogEvent logEvent) { return this.attributeMapConverter @@ -73,18 +73,15 @@ private Single convert( .map( attributeMap -> new SpanLogEventPair( - logEvent.getAttributesMap().get(foreignIdAttribute).getString(), + logEvent.getAttributesMap().get(foreignIdAttribute.id()).getString(), new ConvertedLogEvent(attributeMap))); } - static class SpanLogEventPair { + @lombok.Value + @Accessors(fluent = true) + private static class SpanLogEventPair { String spanId; LogEvent logEvent; - - SpanLogEventPair(String spanId, LogEvent logEvent) { - this.spanId = spanId; - this.logEvent = logEvent; - } } @lombok.Value diff --git a/hypertrace-core-graphql-span-schema/src/test/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilderTest.java b/hypertrace-core-graphql-span-schema/src/test/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilderTest.java index dde54524..105b7298 100644 --- a/hypertrace-core-graphql-span-schema/src/test/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilderTest.java +++ b/hypertrace-core-graphql-span-schema/src/test/java/org/hypertrace/core/graphql/span/dao/SpanLogEventRequestBuilderTest.java @@ -27,13 +27,16 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import org.hypertrace.core.graphql.attributes.AttributeModel; import org.hypertrace.core.graphql.attributes.AttributeStore; import org.hypertrace.core.graphql.common.request.AttributeAssociation; import org.hypertrace.core.graphql.common.request.AttributeRequest; +import org.hypertrace.core.graphql.common.request.AttributeRequestBuilder; import org.hypertrace.core.graphql.common.request.FilterRequestBuilder; import org.hypertrace.core.graphql.common.request.ResultSetRequest; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterArgument; import org.hypertrace.core.graphql.common.utils.Converter; +import org.hypertrace.core.graphql.span.dao.DaoTestUtil.DefaultAttributeRequest; import org.hypertrace.core.graphql.span.dao.DaoTestUtil.DefaultResultSetRequest; import org.hypertrace.core.graphql.span.dao.DaoTestUtil.DefaultSpanRequest; import org.hypertrace.core.graphql.span.dao.DaoTestUtil.DefaultTimeRange; @@ -57,7 +60,9 @@ class SpanLogEventRequestBuilderTest { @Mock private FilterRequestBuilder filterRequestBuilder; - @Mock AttributeStore attributeStore; + @Mock private AttributeStore attributeStore; + + @Mock private AttributeRequestBuilder attributeRequestBuilder; private SpanLogEventRequestBuilder spanLogEventRequestBuilder; @@ -88,7 +93,11 @@ protected void configure() { spanLogEventRequestBuilder = new SpanLogEventRequestBuilder( - attributeConverter, filterConverter, filterRequestBuilder, attributeStore); + attributeConverter, + filterConverter, + filterRequestBuilder, + attributeStore, + attributeRequestBuilder); doAnswer( invocation -> { @@ -108,6 +117,14 @@ protected void configure() { when(attributeStore.getForeignIdAttribute(any(), anyString(), anyString())) .thenReturn(Single.just(spanIdAttribute.attribute())); + + doAnswer( + invocation -> { + AttributeModel attributeModel = invocation.getArgument(0, AttributeModel.class); + return new DefaultAttributeRequest(attributeModel); + }) + .when(attributeRequestBuilder) + .buildForAttribute(any()); } @Test @@ -159,7 +176,7 @@ void testBuildRequest() { assertEquals( Set.of("attributes", "traceId", "spanId"), logEventsRequest.getSelectionList().stream() - .map(v -> v.getColumnIdentifier().getColumnName()) + .map(expression -> expression.getColumnIdentifier().getColumnName()) .collect(Collectors.toSet())); } @@ -210,7 +227,7 @@ void testBuildRequest_addSpanId() { assertEquals( Set.of("traceId", "spanId"), logEventsRequest.getSelectionList().stream() - .map(v -> v.getColumnIdentifier().getColumnName()) + .map(expression -> expression.getColumnIdentifier().getColumnName()) .collect(Collectors.toSet())); } } diff --git a/hypertrace-core-graphql-span-schema/src/test/java/org/hypertrace/core/graphql/span/dao/SpanLogEventResponseConverterTest.java b/hypertrace-core-graphql-span-schema/src/test/java/org/hypertrace/core/graphql/span/dao/SpanLogEventResponseConverterTest.java index c980e441..26de96d1 100644 --- a/hypertrace-core-graphql-span-schema/src/test/java/org/hypertrace/core/graphql/span/dao/SpanLogEventResponseConverterTest.java +++ b/hypertrace-core-graphql-span-schema/src/test/java/org/hypertrace/core/graphql/span/dao/SpanLogEventResponseConverterTest.java @@ -62,7 +62,37 @@ void testBuildResponse() { Map map = invocation.getArgument(1, Map.class); return Single.just( map.entrySet().stream() - .collect(Collectors.toMap(Entry::getKey, v -> v.getValue().getString()))); + .collect( + Collectors.toMap( + Entry::getKey, valueEntry -> valueEntry.getValue().getString()))); + }) + .when(attributeMapConverter) + .convert(anyCollection(), anyMap()); + + SpanLogEventsResponse response = + spanLogEventResponseConverter + .buildResponse(requestContext, attributeRequests, spansResponse, logEventsResponse) + .blockingGet(); + + assertEquals(spansResponse, response.spansResponse()); + assertEquals(Set.of("span1", "span2"), response.spanIdToLogEvents().keySet()); + } + + @Test + void testBuildResponse_spanIdNotRequested() { + Collection attributeRequests = List.of(traceIdAttribute, attributesAttribute); + + when(attributeStore.getForeignIdAttribute(any(), anyString(), anyString())) + .thenReturn(Single.just(spanIdAttribute.attribute())); + + doAnswer( + invocation -> { + Map map = invocation.getArgument(1, Map.class); + return Single.just( + map.entrySet().stream() + .collect( + Collectors.toMap( + Entry::getKey, valueEntry -> valueEntry.getValue().getString()))); }) .when(attributeMapConverter) .convert(anyCollection(), anyMap());