From 7ea4b70530710312b82c92505eae1d9b9aecd9de Mon Sep 17 00:00:00 2001 From: Aaron Steinfeld Date: Tue, 30 Nov 2021 18:30:51 -0500 Subject: [PATCH 1/7] refactor: add support for attribute expressions --- hypertrace-core-graphql | 2 +- .../graphql/entity/dao/EntityDaoModule.java | 9 +- .../entity/dao/EntityNeighborMapFetcher.java | 2 +- .../dao/GatewayServiceEntityConverter.java | 34 ++++--- .../entity/dao/GatewayServiceEntityDao.java | 29 +++--- .../dao/GatewayServiceEntityEdgeFetcher.java | 23 +++-- ...atewayServiceEntityEdgeTableConverter.java | 3 +- ...erviceEntityInteractionRequestBuilder.java | 9 +- .../joiner/DefaultEntityJoinerBuilder.java | 2 + .../DefaultEntityLabelRequestBuilder.java | 4 +- .../entity/request/EdgeRequestBuilder.java | 25 +++-- .../NeighborEntitiesRequestBuilder.java | 2 + .../DefaultEntityJoinerBuilderTest.java | 5 +- .../DefaultEntityLabelRequestBuilderTest.java | 10 +- .../GatewayServiceSelectionMapConverter.java | 11 ++- .../GroupByArgumentDeserializationConfig.java | 4 + .../explorer/fetcher/ExploreResultMapKey.java | 28 +++--- .../fetcher/ExplorerSelectionFetcher.java | 21 +++-- .../request/DefaultExploreRequestBuilder.java | 36 ++++--- .../request/ExploreOrderArgumentBuilder.java | 5 +- .../ExploreSelectionRequestBuilder.java | 94 +++++++++---------- .../explorer/schema/ExploreResult.java | 4 +- .../schema/argument/GroupByArgument.java | 14 ++- .../ExploreOrderArgumentBuilderTest.java | 8 +- ...gatableOrderByExpressionListConverter.java | 22 +++-- ...selinedConvertedAggregationContainer.java} | 0 ...selinedMetricAggregationMapConverter.java} | 0 .../gateway/GatewayMetricUtilsModule.java | 11 ++- ...etricAggregationContainerMapConverter.java | 17 ++-- .../MetricAggregationExpressionConverter.java | 26 +++-- .../gateway/MetricContainerMapConverter.java | 17 ++-- ...bleOrderArgumentDeserializationConfig.java | 4 + ...efaultMetricAggregationRequestBuilder.java | 28 +++--- .../request/DefaultMetricRequestBuilder.java | 17 ++-- .../request/MetricAggregationRequest.java | 5 +- .../MetricAggregationRequestBuilder.java | 14 +-- .../request/MetricQueryableBuilderUtil.java | 42 ++++++--- .../graphql/metric/request/MetricRequest.java | 5 +- .../metric/request/MetricRequestModule.java | 4 +- .../request/MetricSeriesRequestBuilder.java | 17 ++-- .../schema/MetricAggregationQueryable.java | 16 +++- .../metric/schema/MetricQueryable.java | 16 +++- .../spaces/dao/ExplorerBackedSpacesDao.java | 21 +++-- .../dao/ExplorerBackedSpacesDaoTest.java | 25 ++++- 44 files changed, 440 insertions(+), 251 deletions(-) rename hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/{BaselineConvertedAggregationContainer.java => BaselinedConvertedAggregationContainer.java} (100%) rename hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/{MetricAggregationMapConverter.java => BaselinedMetricAggregationMapConverter.java} (100%) diff --git a/hypertrace-core-graphql b/hypertrace-core-graphql index e7d83ae0..127dbcb6 160000 --- a/hypertrace-core-graphql +++ b/hypertrace-core-graphql @@ -1 +1 @@ -Subproject commit e7d83ae01f46a09da26160b895a4178bab259f58 +Subproject commit 127dbcb6e3c7d5f59671027acb51755e186d8085 diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/EntityDaoModule.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/EntityDaoModule.java index 143b79b0..965c306d 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/EntityDaoModule.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/EntityDaoModule.java @@ -11,6 +11,7 @@ import java.util.Set; import org.hypertrace.core.graphql.common.request.AttributeAssociation; import org.hypertrace.core.graphql.common.request.AttributeRequest; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterArgument; import org.hypertrace.core.graphql.common.utils.BiConverter; import org.hypertrace.core.graphql.common.utils.Converter; @@ -81,19 +82,21 @@ protected void configure() { Collection, Entity, BaselineEntity, - Map>>() {})); + Map>>() {})); requireBinding( Key.get( new TypeLiteral< BiConverter< - Collection, Map, Map>>() {})); + Collection, + Map, + Map>>() {})); requireBinding( Key.get( new TypeLiteral< BiConverter< Collection, Map, - Map>>() {})); + Map>>() {})); } } diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/EntityNeighborMapFetcher.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/EntityNeighborMapFetcher.java index 449f8464..76471a3e 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/EntityNeighborMapFetcher.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/EntityNeighborMapFetcher.java @@ -73,7 +73,7 @@ private Single> mapInteraction private Single> buildInteractionEntry( AttributeRequest neighborIdAttribute, InteractionResponse response) { return this.valueConverter - .convert(response.getInteraction().getAttributeMap().get(neighborIdAttribute.alias())) + .convert(response.getInteraction().getAttributeMap().get(neighborIdAttribute.asMapKey())) .map(String::valueOf) .map(id -> Map.entry(id, response)); } diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityConverter.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityConverter.java index 4d6d69ec..c4b124aa 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityConverter.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityConverter.java @@ -9,11 +9,13 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.function.Function; import java.util.stream.Collectors; import javax.annotation.Nullable; import javax.inject.Inject; import lombok.experimental.Accessors; import org.hypertrace.core.graphql.common.request.AttributeRequest; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.utils.BiConverter; import org.hypertrace.core.graphql.common.utils.TriConverter; import org.hypertrace.gateway.service.v1.baseline.BaselineEntitiesResponse; @@ -31,26 +33,28 @@ import org.hypertrace.graphql.metric.schema.MetricContainer; class GatewayServiceEntityConverter { - private final BiConverter, Map, Map> + private final BiConverter< + Collection, Map, Map> attributeMapConverter; private final TriConverter< Collection, org.hypertrace.gateway.service.v1.entity.Entity, BaselineEntity, - Map> + Map> metricContainerConverter; private final GatewayServiceEntityEdgeLookupConverter edgeLookupConverter; @Inject GatewayServiceEntityConverter( - BiConverter, Map, Map> + BiConverter< + Collection, Map, Map> attributeMapConverter, TriConverter< Collection, org.hypertrace.gateway.service.v1.entity.Entity, BaselineEntity, - Map> + Map> metricContainerConverter, GatewayServiceEntityEdgeLookupConverter edgeLookupConverter) { this.attributeMapConverter = attributeMapConverter; @@ -103,7 +107,7 @@ private BaselineEntity getBaselineEntity( private Map getBaselineEntityMap( BaselineEntitiesResponse baselineResponse) { return baselineResponse.getBaselineEntityList().stream() - .collect(Collectors.toMap(BaselineEntity::getId, entity -> entity)); + .collect(Collectors.toMap(BaselineEntity::getId, Function.identity())); } private Single convertEntity( @@ -121,7 +125,12 @@ private Single convertEntity( (attrMap, containerMap) -> new ConvertedEntity( attrMap - .get(entityRequest.resultSetRequest().idAttribute().attribute().key()) + .get( + entityRequest + .resultSetRequest() + .idAttribute() + .attributeExpression() + .value()) .toString(), entityRequest.entityType(), attrMap, @@ -136,20 +145,19 @@ private Single convertEntity( private static class ConvertedEntity implements Entity { String id; String type; - Map attributeValues; - Map metricContainers; + Map attributeValues; + Map metricContainers; Map incomingEdges; Map outgoingEdges; LabelResultSet labels; - @Override - public Object attribute(String key) { - return this.attributeValues.get(key); + public Object attribute(AttributeExpression attributeExpression) { + return this.attributeValues.get(attributeExpression); } @Override - public MetricContainer metric(String key) { - return this.metricContainers.get(key); + public MetricContainer metric(AttributeExpression attributeExpression) { + return this.metricContainers.get(attributeExpression); } @Override diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java index dba07312..9211674e 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java @@ -11,6 +11,7 @@ import javax.inject.Inject; import javax.inject.Singleton; import lombok.extern.slf4j.Slf4j; +import org.hypertrace.core.graphql.common.request.AttributeRequest; import org.hypertrace.core.graphql.context.GraphQlRequestContext; import org.hypertrace.core.graphql.rx.BoundedIoScheduler; import org.hypertrace.core.graphql.spi.config.GraphQlServiceConfig; @@ -23,6 +24,7 @@ import org.hypertrace.gateway.service.v1.entity.EntitiesResponse; import org.hypertrace.gateway.service.v1.entity.Entity; import org.hypertrace.graphql.entity.health.BaselineDao; +import org.hypertrace.graphql.entity.request.EntityLabelRequest; import org.hypertrace.graphql.entity.request.EntityRequest; import org.hypertrace.graphql.entity.schema.EntityResultSet; import org.hypertrace.graphql.label.joiner.LabelJoiner; @@ -117,21 +119,22 @@ private Single> buildLabelResultSetMap( .flatMap( joiner -> joiner.joinLabels( - entitiesResponse.getEntityList(), getEntityLabelsGetter(request))); - } - - private LabelJoiner.LabelIdGetter getEntityLabelsGetter(EntityRequest request) { - return entity -> Single.just(getLabelAttributeValue(request, entity)); + entitiesResponse.getEntityList(), + entity -> Single.just(getLabelAttributeValue(request, entity)))); } private List getLabelAttributeValue(EntityRequest request, Entity entity) { - Value labelAttributeValue = - entity.getAttributeOrDefault( - request.labelRequest().get().labelIdArrayAttributeRequest().attribute().id(), null); - if (labelAttributeValue == null) { - log.warn("Unable to fetch labels attribute for entity with id {}", entity.getId()); - return Collections.emptyList(); - } - return labelAttributeValue.getStringArrayList(); + return request + .labelRequest() + .map(EntityLabelRequest::labelIdArrayAttributeRequest) + .map(AttributeRequest::asMapKey) + .filter(entity::containsAttribute) + .map(entity::getAttributeOrThrow) + .>map(Value::getStringArrayList) + .orElseGet( + () -> { + log.warn("Unable to fetch labels attribute for entity with id {}", entity.getId()); + return Collections.emptyList(); + }); } } diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityEdgeFetcher.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityEdgeFetcher.java index a272cabe..ae723f78 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityEdgeFetcher.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityEdgeFetcher.java @@ -14,6 +14,7 @@ import javax.inject.Inject; import lombok.experimental.Accessors; import org.hypertrace.core.graphql.common.request.AttributeRequest; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.utils.BiConverter; import org.hypertrace.core.graphql.common.utils.CollectorUtils; import org.hypertrace.gateway.service.v1.common.AggregatedMetricValue; @@ -34,23 +35,25 @@ class GatewayServiceEntityEdgeFetcher { private final EntityNeighborMapFetcher neighborMapFetcher; - private final BiConverter, Map, Map> + private final BiConverter< + Collection, Map, Map> attributeMapConverter; private final BiConverter< Collection, Map, - Map> + Map> baselineMetricAggregationContainerMapConverter; @Inject GatewayServiceEntityEdgeFetcher( EntityNeighborMapFetcher neighborMapFetcher, - BiConverter, Map, Map> + BiConverter< + Collection, Map, Map> attributeMapConverter, BiConverter< Collection, Map, - Map> + Map> baselineMetricAggregationContainerMapConverter) { this.neighborMapFetcher = neighborMapFetcher; this.attributeMapConverter = attributeMapConverter; @@ -127,17 +130,17 @@ private Maybe buildEdge( @Accessors(fluent = true) private static class ConvertedEdge implements Edge { Entity neighbor; - Map attributeValues; - Map metricContainers; + Map attributeValues; + Map metricContainers; @Override - public Object attribute(String key) { - return this.attributeValues.get(key); + public Object attribute(AttributeExpression attributeExpression) { + return this.attributeValues.get(attributeExpression); } @Override - public BaselinedMetricAggregationContainer metric(String key) { - return this.metricContainers.get(key); + public BaselinedMetricAggregationContainer metric(AttributeExpression attributeExpressiony) { + return this.metricContainers.get(attributeExpressiony); } } diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityEdgeTableConverter.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityEdgeTableConverter.java index 879c1cb0..50cf2b84 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityEdgeTableConverter.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityEdgeTableConverter.java @@ -59,7 +59,8 @@ private Single>> groupInteractionsBy private Single> builtInteractionTypeEntry( InteractionResponse response, AttributeRequest neighborType) { - return this.getEntityType(response.getInteraction().getAttributeMap().get(neighborType.alias())) + return this.getEntityType( + response.getInteraction().getAttributeMap().get(neighborType.asMapKey())) .map(entityType -> Map.entry(entityType, response)); } diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityInteractionRequestBuilder.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityInteractionRequestBuilder.java index ce1c6952..d83fc57d 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityInteractionRequestBuilder.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityInteractionRequestBuilder.java @@ -13,6 +13,7 @@ import org.hypertrace.core.graphql.common.request.AttributeAssociation; import org.hypertrace.core.graphql.common.request.AttributeRequest; import org.hypertrace.core.graphql.common.schema.attributes.AttributeScope; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterArgument; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterOperatorType; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterType; @@ -71,9 +72,10 @@ private Single buildEntityTypeFilter(EdgeSetGroupRequest request) { .map( entityTypes -> AttributeAssociation.of( - request.neighborTypeAttribute().attribute(), + request.neighborTypeAttribute().attributeExpression().attribute(), new EntityNeighborTypeFilter( - request.neighborTypeAttribute().attribute().key(), entityTypes))) + request.neighborTypeAttribute().attributeExpression().value(), + entityTypes))) .flatMap(filterAssociation -> this.filterConverter.convert(Set.of(filterAssociation))); } @@ -81,7 +83,8 @@ private Single buildEntityTypeFilter(EdgeSetGroupRequest request) { @Accessors(fluent = true) private static class EntityNeighborTypeFilter implements FilterArgument { FilterType type = FilterType.ATTRIBUTE; - String key; + String key = null; + AttributeExpression keyExpression; FilterOperatorType operator = FilterOperatorType.IN; Collection value; AttributeScope idType = null; diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/joiner/DefaultEntityJoinerBuilder.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/joiner/DefaultEntityJoinerBuilder.java index ed563004..2d210e34 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/joiner/DefaultEntityJoinerBuilder.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/joiner/DefaultEntityJoinerBuilder.java @@ -42,6 +42,7 @@ import org.hypertrace.core.graphql.common.request.ResultSetRequestBuilder; import org.hypertrace.core.graphql.common.schema.arguments.TimeRangeArgument; import org.hypertrace.core.graphql.common.schema.attributes.AttributeScope; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterArgument; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterOperatorType; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterType; @@ -326,6 +327,7 @@ private static class InstantTimeRange implements TimeRangeArgument { private static class EntityIdFilter implements FilterArgument { FilterType type = FilterType.ID; String key = null; + AttributeExpression keyExpression = null; FilterOperatorType operator = FilterOperatorType.IN; Collection value; AttributeScope idType = null; diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/request/DefaultEntityLabelRequestBuilder.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/request/DefaultEntityLabelRequestBuilder.java index bf8aa986..e3ca7340 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/request/DefaultEntityLabelRequestBuilder.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/request/DefaultEntityLabelRequestBuilder.java @@ -11,6 +11,7 @@ import lombok.experimental.Accessors; import org.hypertrace.core.graphql.common.request.AttributeRequest; import org.hypertrace.core.graphql.common.request.AttributeRequestBuilder; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.results.ResultSet; import org.hypertrace.core.graphql.context.GraphQlRequestContext; import org.hypertrace.core.graphql.utils.schema.GraphQlSelectionFinder; @@ -66,7 +67,8 @@ private boolean isLabelFieldRequested( private Single> buildRequest( GraphQlRequestContext context, String scope) { return this.attributeRequestBuilder - .buildForKey(context, scope, LABELS_ATTRIBUTE_KEY) + .buildForAttributeExpression( + context, scope, AttributeExpression.forAttributeKey(LABELS_ATTRIBUTE_KEY)) .map(DefaultLabelRequest::new) .map(Optional::of); } diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/request/EdgeRequestBuilder.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/request/EdgeRequestBuilder.java index 9ab2cc40..4cad1968 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/request/EdgeRequestBuilder.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/request/EdgeRequestBuilder.java @@ -19,6 +19,7 @@ import org.hypertrace.core.graphql.common.request.AttributeRequest; import org.hypertrace.core.graphql.common.request.AttributeRequestBuilder; import org.hypertrace.core.graphql.common.schema.arguments.TimeRangeArgument; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.results.ResultSet; import org.hypertrace.core.graphql.context.GraphQlRequestContext; import org.hypertrace.core.graphql.deserialization.ArgumentDeserializer; @@ -150,11 +151,15 @@ private Single getNeighborIdAttribute( GraphQlRequestContext context, EdgeType edgeType) { switch (edgeType) { case INCOMING: - return this.attributeRequestBuilder.buildForKey( - context, HypertraceAttributeScopeString.INTERACTION, INCOMING_ENTITY_ID_KEY); + return this.attributeRequestBuilder.buildForAttributeExpression( + context, + HypertraceAttributeScopeString.INTERACTION, + AttributeExpression.forAttributeKey(INCOMING_ENTITY_ID_KEY)); case OUTGOING: - return this.attributeRequestBuilder.buildForKey( - context, HypertraceAttributeScopeString.INTERACTION, OUTGOING_ENTITY_ID_KEY); + return this.attributeRequestBuilder.buildForAttributeExpression( + context, + HypertraceAttributeScopeString.INTERACTION, + AttributeExpression.forAttributeKey(OUTGOING_ENTITY_ID_KEY)); default: return Single.error(new IllegalStateException("Unexpected value: " + edgeType)); } @@ -164,11 +169,15 @@ private Single getNeighborTypeAttribute( GraphQlRequestContext context, EdgeType edgeType) { switch (edgeType) { case INCOMING: - return this.attributeRequestBuilder.buildForKey( - context, HypertraceAttributeScopeString.INTERACTION, INCOMING_ENTITY_TYPE_KEY); + return this.attributeRequestBuilder.buildForAttributeExpression( + context, + HypertraceAttributeScopeString.INTERACTION, + AttributeExpression.forAttributeKey(INCOMING_ENTITY_TYPE_KEY)); case OUTGOING: - return this.attributeRequestBuilder.buildForKey( - context, HypertraceAttributeScopeString.INTERACTION, OUTGOING_ENTITY_TYPE_KEY); + return this.attributeRequestBuilder.buildForAttributeExpression( + context, + HypertraceAttributeScopeString.INTERACTION, + AttributeExpression.forAttributeKey(OUTGOING_ENTITY_TYPE_KEY)); default: return Single.error(new IllegalStateException("Unexpected value: " + edgeType)); } diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/request/NeighborEntitiesRequestBuilder.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/request/NeighborEntitiesRequestBuilder.java index be59a4b5..1d888a59 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/request/NeighborEntitiesRequestBuilder.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/request/NeighborEntitiesRequestBuilder.java @@ -23,6 +23,7 @@ import org.hypertrace.core.graphql.common.request.ResultSetRequestBuilder; import org.hypertrace.core.graphql.common.schema.arguments.TimeRangeArgument; import org.hypertrace.core.graphql.common.schema.attributes.AttributeScope; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterArgument; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterOperatorType; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterType; @@ -163,6 +164,7 @@ private Stream getNeighborFields(SelectedField edgeField) { private static class EntityNeighborIdFilter implements FilterArgument { FilterType type = FilterType.ID; String key = null; + AttributeExpression keyExpression = null; FilterOperatorType operator = FilterOperatorType.IN; Collection value; AttributeScope idType = null; diff --git a/hypertrace-graphql-entity-schema/src/test/java/org/hypertrace/graphql/entity/joiner/DefaultEntityJoinerBuilderTest.java b/hypertrace-graphql-entity-schema/src/test/java/org/hypertrace/graphql/entity/joiner/DefaultEntityJoinerBuilderTest.java index cc92526e..b459412c 100644 --- a/hypertrace-graphql-entity-schema/src/test/java/org/hypertrace/graphql/entity/joiner/DefaultEntityJoinerBuilderTest.java +++ b/hypertrace-graphql-entity-schema/src/test/java/org/hypertrace/graphql/entity/joiner/DefaultEntityJoinerBuilderTest.java @@ -33,6 +33,7 @@ import org.hypertrace.core.graphql.common.request.ResultSetRequest; import org.hypertrace.core.graphql.common.request.ResultSetRequestBuilder; import org.hypertrace.core.graphql.common.schema.arguments.TimeRangeArgument; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterArgument; import org.hypertrace.core.graphql.context.GraphQlRequestContext; import org.hypertrace.core.graphql.deserialization.ArgumentDeserializer; @@ -331,7 +332,7 @@ private static class TestEntity implements Entity { String id; @Override - public Object attribute(String key) { + public Object attribute(AttributeExpression attributeExpression) { return null; } @@ -346,7 +347,7 @@ public EdgeResultSet outgoingEdges(EntityType neighborType, String neighborScope } @Override - public MetricContainer metric(String key) { + public MetricContainer metric(AttributeExpression attributeExpression) { return null; } diff --git a/hypertrace-graphql-entity-schema/src/test/java/org/hypertrace/graphql/entity/request/DefaultEntityLabelRequestBuilderTest.java b/hypertrace-graphql-entity-schema/src/test/java/org/hypertrace/graphql/entity/request/DefaultEntityLabelRequestBuilderTest.java index da20392b..b3bd9238 100644 --- a/hypertrace-graphql-entity-schema/src/test/java/org/hypertrace/graphql/entity/request/DefaultEntityLabelRequestBuilderTest.java +++ b/hypertrace-graphql-entity-schema/src/test/java/org/hypertrace/graphql/entity/request/DefaultEntityLabelRequestBuilderTest.java @@ -1,6 +1,7 @@ package org.hypertrace.graphql.entity.request; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; @@ -15,6 +16,7 @@ import java.util.stream.Stream; import org.hypertrace.core.graphql.common.request.AttributeRequest; import org.hypertrace.core.graphql.common.request.AttributeRequestBuilder; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.context.GraphQlRequestContext; import org.hypertrace.core.graphql.utils.schema.GraphQlSelectionFinder; import org.junit.jupiter.api.BeforeEach; @@ -58,7 +60,8 @@ void test_buildLabelRequestIfPresentInResultSet_returnsLabelRequest() { when(mockSelectionFinder.findSelections(eq(mockSelectionSet), any())) .thenReturn(Stream.of(mock(SelectedField.class))); AttributeRequest mockAttributeRequest = mock(AttributeRequest.class); - when(attributeRequestBuilder.buildForKey(eq(mockRequestContext), any(), eq("labels"))) + when(attributeRequestBuilder.buildForAttributeExpression( + eq(mockRequestContext), any(), eq(AttributeExpression.forAttributeKey("labels")))) .thenReturn(Single.just(mockAttributeRequest)); Optional entityLabelRequestOptional = this.entityLabelRequestBuilder @@ -76,7 +79,8 @@ void test_buildLabelRequestIfPresentInAnyEntity_returnsLabelRequest() { when(mockSelectionFinder.findSelections(eq(mockSelectionSet), any())) .thenReturn(Stream.of(mock(SelectedField.class))); AttributeRequest mockAttributeRequest = mock(AttributeRequest.class); - when(attributeRequestBuilder.buildForKey(eq(mockRequestContext), any(), eq("labels"))) + when(attributeRequestBuilder.buildForAttributeExpression( + eq(mockRequestContext), any(), eq(AttributeExpression.forAttributeKey("labels")))) .thenReturn(Single.just(mockAttributeRequest)); Optional entityLabelRequestOptional = this.entityLabelRequestBuilder diff --git a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/dao/GatewayServiceSelectionMapConverter.java b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/dao/GatewayServiceSelectionMapConverter.java index 5eda21bf..4c3598fe 100644 --- a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/dao/GatewayServiceSelectionMapConverter.java +++ b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/dao/GatewayServiceSelectionMapConverter.java @@ -67,12 +67,13 @@ private Observable> buildAttributeMapEntri private Single> buildAttributeMapEntry( AttributeRequest attributeRequest, Row row) { return this.valueConverter - .convert(row.getColumnsOrThrow(attributeRequest.alias())) - .flatMap(value -> this.buildSelection(attributeRequest.attribute(), value)) + .convert(row.getColumnsOrThrow(attributeRequest.asMapKey())) + .flatMap( + value -> this.buildSelection(attributeRequest.attributeExpression().attribute(), value)) .map( selection -> Map.entry( - ExploreResultMapKey.basicAttribute(attributeRequest.attribute().key()), + ExploreResultMapKey.attribute(attributeRequest.attributeExpression().value()), selection)); } @@ -87,7 +88,9 @@ private Single> buildAggregationMapEntry( MetricAggregationRequest aggregationRequest, Row row) { return this.valueConverter .convert(row.getColumnsOrThrow(aggregationRequest.alias())) - .flatMap(value -> this.buildSelection(aggregationRequest.attribute(), value)) + .flatMap( + value -> + this.buildSelection(aggregationRequest.attributeExpression().attribute(), value)) .zipWith( this.aggregationTypeConverter.convert(aggregationRequest.aggregation()), (selection, aggregation) -> diff --git a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/deserialization/GroupByArgumentDeserializationConfig.java b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/deserialization/GroupByArgumentDeserializationConfig.java index 2abe229f..f878f40c 100644 --- a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/deserialization/GroupByArgumentDeserializationConfig.java +++ b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/deserialization/GroupByArgumentDeserializationConfig.java @@ -7,6 +7,7 @@ import lombok.NoArgsConstructor; import lombok.Value; import lombok.experimental.Accessors; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.deserialization.ArgumentDeserializationConfig; import org.hypertrace.graphql.explorer.schema.argument.GroupByArgument; @@ -36,6 +37,9 @@ private static class DefaultGroupByArgument implements GroupByArgument { @JsonProperty(GROUP_BY_KEYS_KEY) List keys; + @JsonProperty(GROUP_BY_EXPRESSIONS_KEY) + List expressions; + @JsonProperty(GROUP_BY_INCLUDE_REST_KEY) boolean includeRest; diff --git a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/fetcher/ExploreResultMapKey.java b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/fetcher/ExploreResultMapKey.java index ad042a2a..665a906c 100644 --- a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/fetcher/ExploreResultMapKey.java +++ b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/fetcher/ExploreResultMapKey.java @@ -12,42 +12,48 @@ import lombok.AllArgsConstructor; import lombok.Value; import org.hypertrace.core.graphql.common.schema.attributes.MetricAggregationType; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.graphql.metric.request.MetricAggregationRequest; import org.hypertrace.graphql.metric.request.MetricArguments; @Value @AllArgsConstructor(access = AccessLevel.PRIVATE) public class ExploreResultMapKey { - @Nonnull String key; + @Nonnull AttributeExpression attributeExpression; @Nullable MetricAggregationType aggregationType; @Nullable List arguments; - public static ExploreResultMapKey basicAttribute(String attributeKey) { - return new ExploreResultMapKey(attributeKey, null, null); + public static ExploreResultMapKey attribute(AttributeExpression attributeExpression) { + return new ExploreResultMapKey(attributeExpression, null, null); } public static ExploreResultMapKey forAggregationRequest( MetricAggregationRequest aggregationRequest, MetricAggregationType aggregationType) { return new ExploreResultMapKey( - aggregationRequest.attribute().key(), aggregationType, aggregationRequest.arguments()); + aggregationRequest.attributeExpression().value(), + aggregationType, + aggregationRequest.arguments()); } public static ExploreResultMapKey basicAggregation( - String attributeKey, MetricAggregationType aggregationType) { - return new ExploreResultMapKey(attributeKey, aggregationType, Collections.emptyList()); + AttributeExpression attributeExpression, MetricAggregationType aggregationType) { + return new ExploreResultMapKey(attributeExpression, aggregationType, Collections.emptyList()); } - public static ExploreResultMapKey avgRateAggregation(String attributeKey, Duration duration) { + public static ExploreResultMapKey avgRateAggregation( + AttributeExpression attributeExpression, Duration duration) { return new ExploreResultMapKey( - attributeKey, AVGRATE, MetricArguments.avgRateWithPeriod(duration)); + attributeExpression, AVGRATE, MetricArguments.avgRateWithPeriod(duration)); } - public static ExploreResultMapKey percentileAggregation(String attributeKey, int value) { + public static ExploreResultMapKey percentileAggregation( + AttributeExpression attributeExpression, int value) { return new ExploreResultMapKey( - attributeKey, PERCENTILE, MetricArguments.percentileWithSize(value)); + attributeExpression, PERCENTILE, MetricArguments.percentileWithSize(value)); } public static ExploreResultMapKey intervalStart() { - return new ExploreResultMapKey("__intervalStart__", null, null); + return new ExploreResultMapKey( + AttributeExpression.forAttributeKey("__intervalStart__"), null, null); } } diff --git a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/fetcher/ExplorerSelectionFetcher.java b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/fetcher/ExplorerSelectionFetcher.java index 95a85706..36c49ad7 100644 --- a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/fetcher/ExplorerSelectionFetcher.java +++ b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/fetcher/ExplorerSelectionFetcher.java @@ -1,9 +1,9 @@ package org.hypertrace.graphql.explorer.fetcher; import static java.util.Objects.requireNonNull; +import static org.hypertrace.graphql.explorer.fetcher.ExploreResultMapKey.attribute; import static org.hypertrace.graphql.explorer.fetcher.ExploreResultMapKey.avgRateAggregation; import static org.hypertrace.graphql.explorer.fetcher.ExploreResultMapKey.basicAggregation; -import static org.hypertrace.graphql.explorer.fetcher.ExploreResultMapKey.basicAttribute; import static org.hypertrace.graphql.explorer.fetcher.ExploreResultMapKey.percentileAggregation; import graphql.schema.DataFetcher; @@ -16,6 +16,7 @@ import javax.inject.Inject; import org.hypertrace.core.graphql.common.fetcher.InjectableDataFetcher; import org.hypertrace.core.graphql.common.schema.attributes.MetricAggregationType; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.time.TimeUnit; import org.hypertrace.core.graphql.deserialization.ArgumentDeserializer; import org.hypertrace.graphql.explorer.schema.ExploreResult; @@ -57,9 +58,14 @@ public CompletableFuture get(DataFetchingEnvironment environment) { } private ExploreResultMapKey getKeyForArguments(Map arguments) { - String key = + AttributeExpression attributeExpression = this.argumentDeserializer - .deserializePrimitive(arguments, SelectionKeyArgument.class) + .deserializeObject(arguments, AttributeExpression.class) + .or( + () -> + this.argumentDeserializer + .deserializePrimitive(arguments, SelectionKeyArgument.class) + .map(AttributeExpression::forAttributeKey)) .orElseThrow(); @Nullable MetricAggregationType aggregationType = @@ -67,7 +73,7 @@ private ExploreResultMapKey getKeyForArguments(Map arguments) { .deserializePrimitive(arguments, SelectionAggregationTypeArgument.class) .orElse(null); if (aggregationType == null) { - return basicAttribute(key); + return attribute(attributeExpression); } @Nullable @@ -86,9 +92,10 @@ private ExploreResultMapKey getKeyForArguments(Map arguments) { switch (aggregationType) { case AVGRATE: return avgRateAggregation( - key, Duration.of(requireNonNull(selectionSize), requireNonNull(selectionUnit))); + attributeExpression, + Duration.of(requireNonNull(selectionSize), requireNonNull(selectionUnit))); case PERCENTILE: - return percentileAggregation(key, requireNonNull(selectionSize)); + return percentileAggregation(attributeExpression, requireNonNull(selectionSize)); case COUNT: case AVG: case SUM: @@ -96,7 +103,7 @@ private ExploreResultMapKey getKeyForArguments(Map arguments) { case MAX: case DISTINCTCOUNT: default: - return basicAggregation(key, aggregationType); + return basicAggregation(attributeExpression, aggregationType); } } } diff --git a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/request/DefaultExploreRequestBuilder.java b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/request/DefaultExploreRequestBuilder.java index 8f44e9ef..0d51aa71 100644 --- a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/request/DefaultExploreRequestBuilder.java +++ b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/request/DefaultExploreRequestBuilder.java @@ -2,11 +2,11 @@ import static io.reactivex.rxjava3.core.Single.zip; import static java.util.Collections.emptyList; -import static java.util.Collections.emptySet; import graphql.schema.DataFetchingFieldSelectionSet; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Single; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -20,11 +20,11 @@ import org.hypertrace.core.graphql.common.request.AttributeRequestBuilder; import org.hypertrace.core.graphql.common.request.FilterRequestBuilder; import org.hypertrace.core.graphql.common.schema.arguments.TimeRangeArgument; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterArgument; import org.hypertrace.core.graphql.common.schema.results.arguments.page.LimitArgument; import org.hypertrace.core.graphql.common.schema.results.arguments.page.OffsetArgument; import org.hypertrace.core.graphql.common.schema.results.arguments.space.SpaceArgument; -import org.hypertrace.core.graphql.common.utils.attributes.AttributeAssociator; import org.hypertrace.core.graphql.common.utils.attributes.AttributeScopeStringTranslator; import org.hypertrace.core.graphql.context.GraphQlRequestContext; import org.hypertrace.core.graphql.deserialization.ArgumentDeserializer; @@ -42,7 +42,6 @@ class DefaultExploreRequestBuilder implements ExploreRequestBuilder { private final AttributeRequestBuilder attributeRequestBuilder; private final ArgumentDeserializer argumentDeserializer; - private final AttributeAssociator attributeAssociator; private final ExploreSelectionRequestBuilder selectionRequestBuilder; private final FilterRequestBuilder filterRequestBuilder; private final AttributeScopeStringTranslator scopeStringTranslator; @@ -52,14 +51,12 @@ class DefaultExploreRequestBuilder implements ExploreRequestBuilder { DefaultExploreRequestBuilder( AttributeRequestBuilder attributeRequestBuilder, ArgumentDeserializer argumentDeserializer, - AttributeAssociator attributeAssociator, ExploreSelectionRequestBuilder selectionRequestBuilder, FilterRequestBuilder filterRequestBuilder, AttributeScopeStringTranslator scopeStringTranslator, ExploreOrderArgumentBuilder exploreOrderArgumentBuilder) { this.attributeRequestBuilder = attributeRequestBuilder; this.argumentDeserializer = argumentDeserializer; - this.attributeAssociator = attributeAssociator; this.selectionRequestBuilder = selectionRequestBuilder; this.filterRequestBuilder = filterRequestBuilder; this.scopeStringTranslator = scopeStringTranslator; @@ -123,8 +120,8 @@ private Single build( Optional spaceId = this.argumentDeserializer.deserializePrimitive(arguments, SpaceArgument.class); - Set groupByKeys = - groupBy.map(GroupByArgument::keys).map(Set::copyOf).orElse(emptySet()); + Set groupByExpressions = + groupBy.map(this::resolveGroupByExpressions).orElseGet(Collections::emptySet); Optional intervalArgument = this.argumentDeserializer.deserializeObject(arguments, IntervalArgument.class); @@ -148,7 +145,7 @@ private Single build( aggregationSelections, orderArguments, filterSingle, - this.buildGroupByAttributes(requestContext, explorerScope, groupByKeys), + this.buildGroupByAttributes(requestContext, explorerScope, groupByExpressions), (attributes, aggregations, orders, filters, groupByAttribute) -> new DefaultExploreRequest( requestContext, @@ -168,12 +165,29 @@ private Single build( } private Single> buildGroupByAttributes( - GraphQlRequestContext context, String explorerScope, Set groupByKeys) { - return Observable.fromIterable(groupByKeys) - .flatMapSingle(key -> this.attributeRequestBuilder.buildForKey(context, explorerScope, key)) + GraphQlRequestContext context, + String explorerScope, + Set groupByExpressions) { + return Observable.fromIterable(groupByExpressions) + .flatMapSingle( + expression -> + this.attributeRequestBuilder.buildForAttributeExpression( + context, explorerScope, expression)) .collect(Collectors.toUnmodifiableSet()); } + private Set resolveGroupByExpressions(GroupByArgument groupByArgument) { + return Optional.ofNullable(groupByArgument.expressions()) + .map(Set::copyOf) + .orElseGet( + () -> + Optional.ofNullable(groupByArgument.keys()) + .orElseGet(Collections::emptyList) + .stream() + .map(AttributeExpression::forAttributeKey) + .collect(Collectors.toUnmodifiableSet())); + } + @Value @Accessors(fluent = true) private static class DefaultExploreRequest implements ExploreRequest { diff --git a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/request/ExploreOrderArgumentBuilder.java b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/request/ExploreOrderArgumentBuilder.java index 6aa63979..7204d1e4 100644 --- a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/request/ExploreOrderArgumentBuilder.java +++ b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/request/ExploreOrderArgumentBuilder.java @@ -37,7 +37,8 @@ Single> buildList( private Single buildExploreOrderArgument( GraphQlRequestContext requestContext, String scope, AggregatableOrderArgument argument) { - if (ExploreResult.EXPLORE_RESULT_INTERVAL_START_KEY.equals(argument.key())) { + if (ExploreResult.EXPLORE_RESULT_INTERVAL_START_KEY.equals( + argument.resolvedKeyExpression().key())) { return this.buildIntervalStartExploreOrderArgument(argument); } return this.buildAttributeExploreOrderArgument(requestContext, scope, argument); @@ -51,7 +52,7 @@ private Single buildIntervalStartExploreOrderArgument( private Single buildAttributeExploreOrderArgument( GraphQlRequestContext requestContext, String scope, AggregatableOrderArgument argument) { return this.attributeStore - .get(requestContext, scope, argument.key()) + .get(requestContext, scope, argument.resolvedKeyExpression().key()) .map(model -> new AttributeExploreOrderArgument(argument, Optional.of(model))); } diff --git a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/request/ExploreSelectionRequestBuilder.java b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/request/ExploreSelectionRequestBuilder.java index 9d830e62..48b31b01 100644 --- a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/request/ExploreSelectionRequestBuilder.java +++ b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/request/ExploreSelectionRequestBuilder.java @@ -18,14 +18,14 @@ import javax.inject.Inject; import lombok.AllArgsConstructor; import lombok.Value; -import org.hypertrace.core.graphql.attributes.AttributeModel; import org.hypertrace.core.graphql.attributes.AttributeModelMetricAggregationType; -import org.hypertrace.core.graphql.attributes.AttributeStore; import org.hypertrace.core.graphql.common.request.AttributeRequest; import org.hypertrace.core.graphql.common.request.AttributeRequestBuilder; import org.hypertrace.core.graphql.common.schema.attributes.MetricAggregationType; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.time.TimeUnit; import org.hypertrace.core.graphql.common.utils.Converter; +import org.hypertrace.core.graphql.common.utils.attributes.AttributeAssociator; import org.hypertrace.core.graphql.context.GraphQlRequestContext; import org.hypertrace.core.graphql.deserialization.ArgumentDeserializer; import org.hypertrace.core.graphql.utils.schema.GraphQlSelectionFinder; @@ -40,10 +40,9 @@ import org.hypertrace.graphql.metric.request.MetricArguments; class ExploreSelectionRequestBuilder { - private final GraphQlSelectionFinder selectionFinder; private final ArgumentDeserializer argumentDeserializer; - private final AttributeStore attributeStore; + private final AttributeAssociator attributeAssociator; private final Converter aggregationTypeConverter; private final AttributeRequestBuilder attributeRequestBuilder; @@ -53,14 +52,14 @@ class ExploreSelectionRequestBuilder { ExploreSelectionRequestBuilder( GraphQlSelectionFinder selectionFinder, ArgumentDeserializer argumentDeserializer, - AttributeStore attributeStore, + AttributeAssociator attributeAssociator, Converter aggregationTypeConverter, AttributeRequestBuilder attributeRequestBuilder, MetricAggregationRequestBuilder aggregationRequestBuilder) { this.selectionFinder = selectionFinder; this.argumentDeserializer = argumentDeserializer; - this.attributeStore = attributeStore; + this.attributeAssociator = attributeAssociator; this.aggregationTypeConverter = aggregationTypeConverter; this.attributeRequestBuilder = attributeRequestBuilder; this.aggregationRequestBuilder = aggregationRequestBuilder; @@ -70,9 +69,11 @@ Single> getAttributeSelections( GraphQlRequestContext requestContext, String explorerScope, DataFetchingFieldSelectionSet exploreSelectionSet) { - return this.getSelections( - requestContext, explorerScope, exploreSelectionSet, SelectionType.ATTRIBUTE) - .map(arguments -> this.attributeRequestBuilder.buildForAttribute(arguments.getAttribute())) + return this.getSelections(exploreSelectionSet, SelectionType.ATTRIBUTE) + .flatMapSingle( + arguments -> + this.attributeRequestBuilder.buildForAttributeExpression( + requestContext, explorerScope, arguments.getAttributeExpression())) .collect(Collectors.toUnmodifiableSet()); } @@ -80,15 +81,14 @@ Single> getAggregationSelections( GraphQlRequestContext requestContext, String explorerScope, DataFetchingFieldSelectionSet exploreSelectionSet) { - return this.buildAggregationRequests(requestContext, explorerScope, exploreSelectionSet) + return this.getSelections(exploreSelectionSet, SelectionType.AGGREGATION) + .flatMapSingle( + arguments -> this.buildAggregationRequest(requestContext, explorerScope, arguments)) .collect(Collectors.toUnmodifiableSet()); } private Observable getSelections( - GraphQlRequestContext requestContext, - String explorerScope, - DataFetchingFieldSelectionSet exploreSelectionSet, - SelectionType selectionType) { + DataFetchingFieldSelectionSet exploreSelectionSet, SelectionType selectionType) { return Observable.fromStream( this.selectionFinder.findSelections( exploreSelectionSet, @@ -97,30 +97,30 @@ private Observable getSelections( List.of( RESULT_SET_RESULTS_NAME, ExploreResult.EXPLORE_RESULT_SELECTION_KEY)) .build())) - .flatMapSingle(field -> this.getSelectionArguments(requestContext, explorerScope, field)) + .map(this::getSelectionArguments) .filter(arguments -> arguments.getSelectionType().equals(selectionType)); } - private Single getSelectionArguments( - GraphQlRequestContext requestContext, String explorerScope, SelectedField selectedField) { - String key = + private SelectionArguments getSelectionArguments(SelectedField selectedField) { + AttributeExpression attributeExpression = this.argumentDeserializer - .deserializePrimitive(selectedField.getArguments(), SelectionKeyArgument.class) + .deserializeObject(selectedField.getArguments(), AttributeExpression.class) + .or( + () -> + this.argumentDeserializer + .deserializePrimitive( + selectedField.getArguments(), SelectionKeyArgument.class) + .map(AttributeExpression::forAttributeKey)) .orElseThrow(); - return this.attributeStore - .get(requestContext, explorerScope, key) - .map(attribute -> this.getSelectionArguments(attribute, selectedField)); - } - - private SelectionArguments getSelectionArguments( - AttributeModel attribute, SelectedField selectedField) { return this.getAggregationType(selectedField) .map( aggregationType -> new SelectionArguments( - attribute, aggregationType, this.getArguments(selectedField, aggregationType))) - .orElse(new SelectionArguments(attribute)); + attributeExpression, + aggregationType, + this.getArguments(selectedField, aggregationType))) + .orElse(new SelectionArguments(attributeExpression)); } private Optional getAggregationType( @@ -132,20 +132,20 @@ private Optional getAggregationType( .or(Optional::empty); } - Observable buildAggregationRequests( - GraphQlRequestContext requestContext, - String explorerScope, - DataFetchingFieldSelectionSet exploreSelectionSet) { - return this.getSelections( - requestContext, explorerScope, exploreSelectionSet, SelectionType.AGGREGATION) - .map(this::buildAggregationRequest); - } - - private MetricAggregationRequest buildAggregationRequest(SelectionArguments arguments) { - return this.aggregationRequestBuilder.build( - arguments.getAttribute(), - arguments.getAggregationType(), - arguments.getAggregationArguments()); + private Single buildAggregationRequest( + GraphQlRequestContext requestContext, String explorerScope, SelectionArguments arguments) { + return this.attributeAssociator + .associateAttribute( + requestContext, + explorerScope, + arguments.getAttributeExpression(), + arguments.getAttributeExpression().key()) + .map( + attributeExpressionAttributeAssociation -> + this.aggregationRequestBuilder.build( + attributeExpressionAttributeAssociation, + arguments.getAggregationType(), + arguments.getAggregationArguments())); } private List getArguments( @@ -184,19 +184,19 @@ private enum SelectionType { @AllArgsConstructor private static class SelectionArguments { @Nonnull SelectionType selectionType; - @Nonnull AttributeModel attribute; + @Nonnull AttributeExpression attributeExpression; @Nullable AttributeModelMetricAggregationType aggregationType; @Nullable List aggregationArguments; - SelectionArguments(AttributeModel attribute) { - this(SelectionType.ATTRIBUTE, attribute, null, null); + SelectionArguments(AttributeExpression attributeExpression) { + this(SelectionType.ATTRIBUTE, attributeExpression, null, null); } SelectionArguments( - AttributeModel attribute, + AttributeExpression attributeExpression, AttributeModelMetricAggregationType aggregationType, List aggregationArguments) { - this(SelectionType.AGGREGATION, attribute, aggregationType, aggregationArguments); + this(SelectionType.AGGREGATION, attributeExpression, aggregationType, aggregationArguments); } } } diff --git a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/schema/ExploreResult.java b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/schema/ExploreResult.java index f229e453..e7055967 100644 --- a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/schema/ExploreResult.java +++ b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/schema/ExploreResult.java @@ -7,6 +7,7 @@ import java.time.Instant; import java.util.Map; import org.hypertrace.core.graphql.common.schema.attributes.MetricAggregationType; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.time.TimeUnit; import org.hypertrace.graphql.explorer.fetcher.ExploreResultMapKey; import org.hypertrace.graphql.explorer.fetcher.ExplorerSelectionFetcher; @@ -25,7 +26,8 @@ public interface ExploreResult { @GraphQLName(EXPLORE_RESULT_SELECTION_KEY) @GraphQLDataFetcher(ExplorerSelectionFetcher.class) default Selection selection( - @GraphQLName(SelectionKeyArgument.ARGUMENT_NAME) @GraphQLNonNull String key, + @Deprecated @GraphQLName(SelectionKeyArgument.ARGUMENT_NAME) String key, + @GraphQLName(AttributeExpression.ARGUMENT_NAME) AttributeExpression attributeExpression, @GraphQLName(SelectionAggregationTypeArgument.ARGUMENT_NAME) MetricAggregationType aggregationType, @GraphQLName(SelectionSizeArgument.ARGUMENT_NAME) int size, diff --git a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/schema/argument/GroupByArgument.java b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/schema/argument/GroupByArgument.java index 2c2e0bcf..12141d88 100644 --- a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/schema/argument/GroupByArgument.java +++ b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/schema/argument/GroupByArgument.java @@ -1,9 +1,11 @@ package org.hypertrace.graphql.explorer.schema.argument; +import graphql.annotations.annotationTypes.GraphQLDeprecate; import graphql.annotations.annotationTypes.GraphQLField; import graphql.annotations.annotationTypes.GraphQLName; -import graphql.annotations.annotationTypes.GraphQLNonNull; import java.util.List; +import javax.annotation.Nullable; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; @GraphQLName(GroupByArgument.TYPE_NAME) public interface GroupByArgument { @@ -11,14 +13,22 @@ public interface GroupByArgument { String ARGUMENT_NAME = "groupBy"; String GROUP_BY_KEYS_KEY = "keys"; + String GROUP_BY_EXPRESSIONS_KEY = "expressions"; String GROUP_BY_INCLUDE_REST_KEY = "includeRest"; String GROUP_BY_LIMIT_KEY = "groupLimit"; @GraphQLField - @GraphQLNonNull + @GraphQLDeprecate + @Deprecated + @Nullable @GraphQLName(GROUP_BY_KEYS_KEY) List keys(); + @GraphQLField + @Nullable + @GraphQLName(GROUP_BY_EXPRESSIONS_KEY) + List expressions(); + @GraphQLField @GraphQLName(GROUP_BY_INCLUDE_REST_KEY) boolean includeRest(); diff --git a/hypertrace-graphql-explorer-schema/src/test/java/org/hypertrace/graphql/explorer/request/ExploreOrderArgumentBuilderTest.java b/hypertrace-graphql-explorer-schema/src/test/java/org/hypertrace/graphql/explorer/request/ExploreOrderArgumentBuilderTest.java index bd072f6b..b47d9f7f 100644 --- a/hypertrace-graphql-explorer-schema/src/test/java/org/hypertrace/graphql/explorer/request/ExploreOrderArgumentBuilderTest.java +++ b/hypertrace-graphql-explorer-schema/src/test/java/org/hypertrace/graphql/explorer/request/ExploreOrderArgumentBuilderTest.java @@ -9,6 +9,7 @@ import java.util.Optional; import org.hypertrace.core.graphql.attributes.AttributeModel; import org.hypertrace.core.graphql.attributes.AttributeStore; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.context.GraphQlRequestContext; import org.hypertrace.graphql.explorer.request.ExploreOrderArgument.ExploreOrderArgumentType; import org.hypertrace.graphql.explorer.schema.ExploreResult; @@ -37,9 +38,12 @@ void beforeEach() { @Test void convertsList() { AggregatableOrderArgument firstArg = mock(AggregatableOrderArgument.class); - when(firstArg.key()).thenReturn(ExploreResult.EXPLORE_RESULT_INTERVAL_START_KEY); + when(firstArg.resolvedKeyExpression()) + .thenReturn( + AttributeExpression.forAttributeKey(ExploreResult.EXPLORE_RESULT_INTERVAL_START_KEY)); AggregatableOrderArgument secondArg = mock(AggregatableOrderArgument.class); - when(secondArg.key()).thenReturn("second"); + when(secondArg.resolvedKeyExpression()) + .thenReturn(AttributeExpression.forAttributeKey("second")); AttributeModel mockAttributeModel = mock(AttributeModel.class); when(mockAttributeStore.get(mockRequestContext, MOCK_CONTEXT, "second")) .thenReturn(Single.just(mockAttributeModel)); diff --git a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/AggregatableOrderByExpressionListConverter.java b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/AggregatableOrderByExpressionListConverter.java index 8cb1d75a..4c2cf956 100644 --- a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/AggregatableOrderByExpressionListConverter.java +++ b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/AggregatableOrderByExpressionListConverter.java @@ -10,10 +10,10 @@ import java.util.Optional; import java.util.stream.Collectors; import javax.inject.Inject; -import org.hypertrace.core.graphql.attributes.AttributeModel; import org.hypertrace.core.graphql.attributes.AttributeModelMetricAggregationType; import org.hypertrace.core.graphql.common.request.AttributeAssociation; import org.hypertrace.core.graphql.common.schema.attributes.MetricAggregationType; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.results.arguments.order.OrderDirection; import org.hypertrace.core.graphql.common.utils.Converter; import org.hypertrace.gateway.service.v1.common.Expression; @@ -25,7 +25,8 @@ class AggregatableOrderByExpressionListConverter implements Converter< List>, List> { - private final Converter columnExpressionConverter; + private final Converter, Expression> + columnExpressionConverter; private final MetricAggregationExpressionConverter metricAggregationExpressionConverter; private final Converter sortOrderConverter; private final Converter @@ -33,7 +34,7 @@ class AggregatableOrderByExpressionListConverter @Inject AggregatableOrderByExpressionListConverter( - Converter columnExpressionConverter, + Converter, Expression> columnExpressionConverter, MetricAggregationExpressionConverter metricAggregationExpressionConverter, Converter sortOrderConverter, Converter @@ -63,17 +64,26 @@ private Single buildOrderByExpression( private Single buildSelectionExpression( AttributeAssociation orderArgument) { + AttributeAssociation attributeExpression = + this.buildAttributeExpression(orderArgument); return Maybe.fromOptional(Optional.ofNullable(orderArgument.value().aggregation())) .flatMapSingle(this.aggregationTypeConverter::convert) .flatMapSingle( aggregationType -> orderArgument.value().size() == null ? this.metricAggregationExpressionConverter.convertForNoArgsOrAlias( - orderArgument.attribute(), aggregationType) + attributeExpression, aggregationType) : this.metricAggregationExpressionConverter.convertForArgsButNoAlias( - orderArgument.attribute(), + attributeExpression, aggregationType, List.of(Objects.requireNonNull(orderArgument.value().size())))) - .switchIfEmpty(this.columnExpressionConverter.convert(orderArgument.attribute())); + .switchIfEmpty(this.columnExpressionConverter.convert(attributeExpression)); + } + + private AttributeAssociation buildAttributeExpression( + AttributeAssociation orderArgumentAttributeAssociation) { + return AttributeAssociation.of( + orderArgumentAttributeAssociation.attribute(), + orderArgumentAttributeAssociation.value().resolvedKeyExpression()); } } diff --git a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/BaselineConvertedAggregationContainer.java b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/BaselinedConvertedAggregationContainer.java similarity index 100% rename from hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/BaselineConvertedAggregationContainer.java rename to hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/BaselinedConvertedAggregationContainer.java diff --git a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationMapConverter.java b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/BaselinedMetricAggregationMapConverter.java similarity index 100% rename from hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationMapConverter.java rename to hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/BaselinedMetricAggregationMapConverter.java diff --git a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/GatewayMetricUtilsModule.java b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/GatewayMetricUtilsModule.java index 6581e739..09ba04a8 100644 --- a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/GatewayMetricUtilsModule.java +++ b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/GatewayMetricUtilsModule.java @@ -7,10 +7,10 @@ import java.util.List; import java.util.Map; import java.util.Set; -import org.hypertrace.core.graphql.attributes.AttributeModel; import org.hypertrace.core.graphql.attributes.AttributeModelMetricAggregationType; import org.hypertrace.core.graphql.common.request.AttributeAssociation; import org.hypertrace.core.graphql.common.schema.attributes.MetricAggregationType; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.results.arguments.order.OrderDirection; import org.hypertrace.core.graphql.common.utils.BiConverter; import org.hypertrace.core.graphql.common.utils.Converter; @@ -48,14 +48,14 @@ protected void configure() { Collection, Entity, BaselineEntity, - Map>>() {})) + Map>>() {})) .to(MetricContainerMapConverter.class); bind(Key.get( new TypeLiteral< BiConverter< Collection, Map, - Map>>() {})) + Map>>() {})) .to(MetricAggregationContainerMapConverter.class); bind(Key.get( @@ -65,7 +65,10 @@ protected void configure() { List>>() {})) .to(AggregatableOrderByExpressionListConverter.class); - requireBinding(Key.get(new TypeLiteral>() {})); + requireBinding( + Key.get( + new TypeLiteral< + Converter, Expression>>() {})); requireBinding(Key.get(new TypeLiteral>() {})); requireBinding(Key.get(new TypeLiteral>() {})); requireBinding(Key.get(new TypeLiteral>() {})); diff --git a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationContainerMapConverter.java b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationContainerMapConverter.java index 18f458b8..91e2bfbc 100644 --- a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationContainerMapConverter.java +++ b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationContainerMapConverter.java @@ -10,7 +10,7 @@ import java.util.Map; import java.util.Map.Entry; import javax.inject.Inject; -import org.hypertrace.core.graphql.attributes.AttributeModel; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.utils.BiConverter; import org.hypertrace.gateway.service.v1.common.AggregatedMetricValue; import org.hypertrace.graphql.metric.request.MetricAggregationRequest; @@ -20,7 +20,7 @@ class MetricAggregationContainerMapConverter implements BiConverter< Collection, Map, - Map> { + Map> { private final BaselinedMetricAggregationMapConverter aggregationMapConverter; @@ -31,19 +31,20 @@ class MetricAggregationContainerMapConverter } @Override - public Single> convert( + public Single> convert( Collection metricRequests, Map metricResponses) { return Observable.fromIterable(metricRequests) .distinct() - .groupBy(MetricAggregationRequest::attribute) + .groupBy(request -> request.attributeExpression().value()) .flatMapSingle(requests -> this.buildMetricContainerEntry(requests, metricResponses)) .collect(immutableMapEntryCollector()); } - private Single> buildMetricContainerEntry( - GroupedObservable requestsForAttribute, - Map metricResponses) { + private Single> + buildMetricContainerEntry( + GroupedObservable requestsForAttribute, + Map metricResponses) { return requestsForAttribute .toList() @@ -52,6 +53,6 @@ private Single> buildMetricCo this.aggregationMapConverter.convert( metricRequests, metricResponses, Collections.emptyMap())) .map(BaselinedConvertedAggregationContainer::new) - .map(container -> Map.entry(requestsForAttribute.getKey().key(), container)); + .map(container -> Map.entry(requestsForAttribute.getKey(), container)); } } diff --git a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationExpressionConverter.java b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationExpressionConverter.java index 82447ac2..74ef6c74 100644 --- a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationExpressionConverter.java +++ b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationExpressionConverter.java @@ -11,8 +11,9 @@ import java.util.Set; import java.util.stream.Collectors; import javax.inject.Inject; -import org.hypertrace.core.graphql.attributes.AttributeModel; import org.hypertrace.core.graphql.attributes.AttributeModelMetricAggregationType; +import org.hypertrace.core.graphql.common.request.AttributeAssociation; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.utils.Converter; import org.hypertrace.gateway.service.v1.common.Expression; import org.hypertrace.gateway.service.v1.common.FunctionExpression; @@ -20,13 +21,14 @@ class MetricAggregationExpressionConverter implements Converter, Set> { - private final Converter columnExpressionConverter; + private final Converter, Expression> + columnExpressionConverter; private final FunctionTypeConverter functionTypeConverter; private final Converter literalConverter; @Inject MetricAggregationExpressionConverter( - Converter columnExpressionConverter, + Converter, Expression> columnExpressionConverter, FunctionTypeConverter functionTypeConverter, Converter literalConverter) { this.columnExpressionConverter = columnExpressionConverter; @@ -43,7 +45,7 @@ public Single> convert(Collection metr Single convert(MetricAggregationRequest metricAggregation, String alias) { return this.buildAggregationFunctionExpression( - metricAggregation.attribute(), + metricAggregation.attributeExpression(), metricAggregation.aggregation(), metricAggregation.arguments(), alias) @@ -51,27 +53,31 @@ Single convert(MetricAggregationRequest metricAggregation, String al } Single convertForNoArgsOrAlias( - AttributeModel attribute, AttributeModelMetricAggregationType aggregationType) { - return convertForArgsButNoAlias(attribute, aggregationType, Collections.emptyList()); + AttributeAssociation attributeExpression, + AttributeModelMetricAggregationType aggregationType) { + return convertForArgsButNoAlias(attributeExpression, aggregationType, Collections.emptyList()); } Single convertForArgsButNoAlias( - AttributeModel attribute, + AttributeAssociation attributeExpression, AttributeModelMetricAggregationType aggregationType, List arguments) { return this.buildAggregationFunctionExpression( - attribute, aggregationType, arguments, StringValue.getDefaultInstance().getValue()) + attributeExpression, + aggregationType, + arguments, + StringValue.getDefaultInstance().getValue()) .map(functionExpression -> Expression.newBuilder().setFunction(functionExpression).build()); } private Single buildAggregationFunctionExpression( - AttributeModel attribute, + AttributeAssociation attributeExpression, AttributeModelMetricAggregationType aggregationType, List arguments, String alias) { return zip( functionTypeConverter.convert(aggregationType), - this.columnExpressionConverter.convert(attribute), + this.columnExpressionConverter.convert(attributeExpression), this.convertArguments(arguments), (functionType, columnExpression, argumentExpressionList) -> FunctionExpression.newBuilder() diff --git a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricContainerMapConverter.java b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricContainerMapConverter.java index 0b19b8b1..72853731 100644 --- a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricContainerMapConverter.java +++ b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricContainerMapConverter.java @@ -13,7 +13,7 @@ import java.util.Map.Entry; import java.util.stream.Collectors; import javax.inject.Inject; -import org.hypertrace.core.graphql.attributes.AttributeModel; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.time.TimeUnit; import org.hypertrace.core.graphql.common.utils.CollectorUtils; import org.hypertrace.core.graphql.common.utils.TriConverter; @@ -29,7 +29,10 @@ class MetricContainerMapConverter implements TriConverter< - Collection, Entity, BaselineEntity, Map> { + Collection, + Entity, + BaselineEntity, + Map> { private final BaselinedMetricAggregationMapConverter aggregationMapConverter; private final MetricSeriesMapConverter seriesMapConverter; @@ -46,17 +49,17 @@ class MetricContainerMapConverter } @Override - public Single> convert( + public Single> convert( Collection metricRequests, Entity entity, BaselineEntity baselineEntity) { return Observable.fromIterable(metricRequests) .distinct() - .groupBy(MetricRequest::attribute) + .groupBy(request -> request.attributeExpression().value()) .flatMapSingle(requests -> this.buildMetricContainerEntry(requests, entity, baselineEntity)) .collect(immutableMapEntryCollector()); } - private Single> buildMetricContainerEntry( - GroupedObservable requestsForAttribute, + private Single> buildMetricContainerEntry( + GroupedObservable requestsForAttribute, Entity entity, BaselineEntity baselineEntity) { return requestsForAttribute @@ -64,7 +67,7 @@ private Single> buildMetricContainerEntry( .flatMap( metricRequests -> this.buildMetricContainerForAttribute(metricRequests, entity, baselineEntity)) - .map(container -> Map.entry(requestsForAttribute.getKey().key(), container)); + .map(container -> Map.entry(requestsForAttribute.getKey(), container)); } private Single buildMetricContainerForAttribute( diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/deserialization/AggregatableOrderArgumentDeserializationConfig.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/deserialization/AggregatableOrderArgumentDeserializationConfig.java index 12346e95..4afbcff5 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/deserialization/AggregatableOrderArgumentDeserializationConfig.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/deserialization/AggregatableOrderArgumentDeserializationConfig.java @@ -8,6 +8,7 @@ import lombok.Value; import lombok.experimental.Accessors; import org.hypertrace.core.graphql.common.schema.attributes.MetricAggregationType; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.results.arguments.order.OrderDirection; import org.hypertrace.core.graphql.deserialization.ArgumentDeserializationConfig; import org.hypertrace.graphql.metric.schema.argument.AggregatableOrderArgument; @@ -42,6 +43,9 @@ private static class DefaultAggregatableOrderArgument implements AggregatableOrd @JsonProperty(ORDER_KEY_NAME) String key; + @JsonProperty(ORDER_KEY_EXPRESSION_NAME) + AttributeExpression keyExpression; + @JsonProperty(METRIC_AGGREGATION_ORDER_AGGREGATION_TYPE) MetricAggregationType aggregation; diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricAggregationRequestBuilder.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricAggregationRequestBuilder.java index b4c36e17..d208490b 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricAggregationRequestBuilder.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricAggregationRequestBuilder.java @@ -23,8 +23,9 @@ import javax.inject.Inject; import lombok.Value; import lombok.experimental.Accessors; -import org.hypertrace.core.graphql.attributes.AttributeModel; import org.hypertrace.core.graphql.attributes.AttributeModelMetricAggregationType; +import org.hypertrace.core.graphql.common.request.AttributeAssociation; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.time.TimeUnit; import org.hypertrace.core.graphql.context.GraphQlRequestContext; import org.hypertrace.core.graphql.deserialization.ArgumentDeserializer; @@ -52,14 +53,15 @@ class DefaultMetricAggregationRequestBuilder implements MetricAggregationRequest @Override public Observable build( - AttributeModel attribute, SelectedField metricAggregationContainerField) { + AttributeAssociation attributeExpression, + SelectedField metricAggregationContainerField) { return Observable.fromStream( this.selectionFinder.findSelections( metricAggregationContainerField.getSelectionSet(), SelectionQuery.builder() .matchesPredicate(field -> this.getAggregationTypeForField(field).isPresent()) .build())) - .map(selectedField -> this.requestForAggregationField(attribute, selectedField)); + .map(selectedField -> this.requestForAggregationField(attributeExpression, selectedField)); } @Override @@ -72,26 +74,27 @@ public Single> build( } public MetricAggregationRequest build( - AttributeModel attribute, + AttributeAssociation attributeExpression, AttributeModelMetricAggregationType aggregationType, List arguments) { - return this.build(attribute, aggregationType, arguments, false); + return this.build(attributeExpression, aggregationType, arguments, false); } - public MetricAggregationRequest build( - AttributeModel attribute, + private MetricAggregationRequest build( + AttributeAssociation attributeExpression, AttributeModelMetricAggregationType aggregationType, List arguments, boolean baseline) { - return new DefaultMetricAggregationRequest(attribute, aggregationType, arguments, baseline); + return new DefaultMetricAggregationRequest( + attributeExpression, aggregationType, arguments, baseline); } private MetricAggregationRequest requestForAggregationField( - AttributeModel attribute, SelectedField field) { + AttributeAssociation attributeExpression, SelectedField field) { AttributeModelMetricAggregationType aggregationType = this.getAggregationTypeForField(field).orElseThrow(); return this.build( - attribute, + attributeExpression, aggregationType, this.getArgumentsForAggregation(aggregationType, field.getArguments()), this.selectionFinder @@ -167,7 +170,7 @@ private Integer percentileSize(Map arguments) { @Value @Accessors(fluent = true) private static class DefaultMetricAggregationRequest implements MetricAggregationRequest { - AttributeModel attribute; + AttributeAssociation attributeExpression; AttributeModelMetricAggregationType aggregation; List arguments; boolean baseline; @@ -175,7 +178,8 @@ private static class DefaultMetricAggregationRequest implements MetricAggregatio @Override public String alias() { return String.format( - "%s_%s_%s", this.aggregation.name(), this.attribute.id(), this.arguments); + "%s_%s_%s", + this.aggregation.name(), this.attributeExpression.attribute().id(), this.arguments); } @Override diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricRequestBuilder.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricRequestBuilder.java index e1120dcb..5c22ee43 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricRequestBuilder.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricRequestBuilder.java @@ -9,7 +9,8 @@ import javax.inject.Inject; import lombok.Value; import lombok.experimental.Accessors; -import org.hypertrace.core.graphql.attributes.AttributeModel; +import org.hypertrace.core.graphql.common.request.AttributeAssociation; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.context.GraphQlRequestContext; class DefaultMetricRequestBuilder implements MetricRequestBuilder { @@ -38,19 +39,21 @@ public Single> build( } private Observable collectAggregationsAndSeries( - AttributeModel attribute, SelectedField metricContainerField) { + AttributeAssociation attributeExpression, + SelectedField metricContainerField) { return Single.zip( this.aggregationRequestBuilder - .build(attribute, metricContainerField) + .build(attributeExpression, metricContainerField) .collect(Collectors.toUnmodifiableList()), this.seriesRequestBuilder - .build(attribute, metricContainerField) + .build(attributeExpression, metricContainerField) .collect(Collectors.toUnmodifiableList()), this.seriesRequestBuilder - .buildBaselineSeriesRequests(attribute, metricContainerField) + .buildBaselineSeriesRequests(attributeExpression, metricContainerField) .collect(Collectors.toUnmodifiableList()), (aggList, seriesList, baselineSeriesList) -> - new DefaultMetricRequest(attribute, aggList, seriesList, baselineSeriesList)) + new DefaultMetricRequest( + attributeExpression, aggList, seriesList, baselineSeriesList)) .cast(MetricRequest.class) .toObservable(); } @@ -58,7 +61,7 @@ private Observable collectAggregationsAndSeries( @Value @Accessors(fluent = true) private static class DefaultMetricRequest implements MetricRequest { - AttributeModel attribute; + AttributeAssociation attributeExpression; List aggregationRequests; List seriesRequests; List baselineSeriesRequests; diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequest.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequest.java index b44e3d28..001434c7 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequest.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequest.java @@ -1,12 +1,13 @@ package org.hypertrace.graphql.metric.request; import java.util.List; -import org.hypertrace.core.graphql.attributes.AttributeModel; import org.hypertrace.core.graphql.attributes.AttributeModelMetricAggregationType; +import org.hypertrace.core.graphql.common.request.AttributeAssociation; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; public interface MetricAggregationRequest { - AttributeModel attribute(); + AttributeAssociation attributeExpression(); AttributeModelMetricAggregationType aggregation(); diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequestBuilder.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequestBuilder.java index ad8918d4..8ff316a1 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequestBuilder.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequestBuilder.java @@ -5,13 +5,15 @@ import io.reactivex.rxjava3.core.Single; import java.util.List; import java.util.stream.Stream; -import org.hypertrace.core.graphql.attributes.AttributeModel; import org.hypertrace.core.graphql.attributes.AttributeModelMetricAggregationType; +import org.hypertrace.core.graphql.common.request.AttributeAssociation; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.context.GraphQlRequestContext; public interface MetricAggregationRequestBuilder { Observable build( - AttributeModel attribute, SelectedField metricAggregationContainerField); + AttributeAssociation attributeExpression, + SelectedField metricAggregationContainerField); Single> build( GraphQlRequestContext context, @@ -19,13 +21,7 @@ Single> build( Stream metricQueryableFieldStream); MetricAggregationRequest build( - AttributeModel attribute, + AttributeAssociation attributeExpression, AttributeModelMetricAggregationType aggregationType, List arguments); - - MetricAggregationRequest build( - AttributeModel attribute, - AttributeModelMetricAggregationType aggregationType, - List arguments, - boolean baseline); } diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricQueryableBuilderUtil.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricQueryableBuilderUtil.java index 2dff48dd..85fbc058 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricQueryableBuilderUtil.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricQueryableBuilderUtil.java @@ -13,8 +13,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import javax.inject.Inject; -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.schema.attributes.arguments.AttributeExpression; +import org.hypertrace.core.graphql.common.utils.attributes.AttributeAssociator; import org.hypertrace.core.graphql.context.GraphQlRequestContext; import org.hypertrace.core.graphql.deserialization.ArgumentDeserializer; import org.hypertrace.core.graphql.utils.schema.GraphQlSelectionFinder; @@ -25,23 +26,23 @@ class MetricQueryableBuilderUtil { private final GraphQlSelectionFinder selectionFinder; private final ArgumentDeserializer argumentDeserializer; - private final AttributeStore attributeStore; + private final AttributeAssociator attributeAssociator; @Inject MetricQueryableBuilderUtil( GraphQlSelectionFinder selectionFinder, ArgumentDeserializer argumentDeserializer, - AttributeStore attributeStore) { + AttributeAssociator attributeAssociator) { this.selectionFinder = selectionFinder; this.argumentDeserializer = argumentDeserializer; - this.attributeStore = attributeStore; + this.attributeAssociator = attributeAssociator; } Single> buildForEachMetricQueryable( GraphQlRequestContext context, String scope, Stream metricQueryableFieldStream, - BiFunction> builder) { + BiFunction, SelectedField, Observable> builder) { return Observable.fromStream(metricQueryableFieldStream) .flatMap(field -> this.buildForEachMetricContainer(context, scope, field, builder)) @@ -52,7 +53,7 @@ private Observable buildForEachMetricContainer( GraphQlRequestContext context, String scope, SelectedField metricQueryableField, - BiFunction> builder) { + BiFunction, SelectedField, Observable> builder) { return Observable.fromStream( this.selectionFinder.findSelections( @@ -68,12 +69,27 @@ private Observable buildForEachMetricContainer( GraphQlRequestContext context, String scope, SelectedField metricContainerField, - Function> builder) { - Optional metricKey = - this.argumentDeserializer.deserializePrimitive( - metricContainerField.getArguments(), MetricKeyArgument.class); - return Maybe.fromOptional(metricKey) - .flatMapSingle(key -> this.attributeStore.get(context, scope, key)) + Function, Observable> builder) { + return this.resolveAttributeExpression(context, scope, metricContainerField) .flatMapObservable(builder::apply); } + + private Maybe> resolveAttributeExpression( + GraphQlRequestContext context, String scope, SelectedField metricContainerField) { + Optional maybeExpression = + this.argumentDeserializer + .deserializeObject(metricContainerField.getArguments(), AttributeExpression.class) + .or( + () -> + this.argumentDeserializer + .deserializePrimitive( + metricContainerField.getArguments(), MetricKeyArgument.class) + .map(AttributeExpression::forAttributeKey)); + + return Maybe.fromOptional(maybeExpression) + .flatMapSingle( + expression -> + this.attributeAssociator.associateAttribute( + context, scope, expression, expression.key())); + } } diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricRequest.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricRequest.java index e491289b..a138b3aa 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricRequest.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricRequest.java @@ -1,10 +1,11 @@ package org.hypertrace.graphql.metric.request; import java.util.List; -import org.hypertrace.core.graphql.attributes.AttributeModel; +import org.hypertrace.core.graphql.common.request.AttributeAssociation; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; public interface MetricRequest { - AttributeModel attribute(); + AttributeAssociation attributeExpression(); List aggregationRequests(); diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricRequestModule.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricRequestModule.java index 1a3a9612..0edf6501 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricRequestModule.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricRequestModule.java @@ -1,7 +1,7 @@ package org.hypertrace.graphql.metric.request; import com.google.inject.AbstractModule; -import org.hypertrace.core.graphql.attributes.AttributeStore; +import org.hypertrace.core.graphql.common.utils.attributes.AttributeAssociator; import org.hypertrace.core.graphql.deserialization.ArgumentDeserializer; import org.hypertrace.core.graphql.utils.schema.GraphQlSelectionFinder; @@ -12,7 +12,7 @@ protected void configure() { bind(MetricRequestBuilder.class).to(DefaultMetricRequestBuilder.class); bind(MetricAggregationRequestBuilder.class).to(DefaultMetricAggregationRequestBuilder.class); - requireBinding(AttributeStore.class); + requireBinding(AttributeAssociator.class); requireBinding(ArgumentDeserializer.class); requireBinding(GraphQlSelectionFinder.class); } diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricSeriesRequestBuilder.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricSeriesRequestBuilder.java index d3e3522c..93c2174f 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricSeriesRequestBuilder.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricSeriesRequestBuilder.java @@ -10,7 +10,8 @@ import javax.inject.Inject; import lombok.Value; import lombok.experimental.Accessors; -import org.hypertrace.core.graphql.attributes.AttributeModel; +import org.hypertrace.core.graphql.common.request.AttributeAssociation; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.time.TimeUnit; import org.hypertrace.core.graphql.deserialization.ArgumentDeserializer; import org.hypertrace.core.graphql.utils.schema.GraphQlSelectionFinder; @@ -35,28 +36,30 @@ class MetricSeriesRequestBuilder { } Observable build( - AttributeModel attribute, SelectedField metricContainerField) { + AttributeAssociation attributeExpression, + SelectedField metricContainerField) { return Observable.fromStream( this.selectionFinder.findSelections( metricContainerField.getSelectionSet(), SelectionQuery.namedChild(METRIC_INTERVAL_CONTAINER_SERIES_KEY))) - .flatMap(field -> this.flattenAggregationsForSeries(attribute, field)); + .flatMap(field -> this.flattenAggregationsForSeries(attributeExpression, field)); } Observable buildBaselineSeriesRequests( - AttributeModel attribute, SelectedField metricContainerField) { + AttributeAssociation attributeExpression, + SelectedField metricContainerField) { return Observable.fromStream( this.selectionFinder.findSelections( metricContainerField.getSelectionSet(), SelectionQuery.namedChild(BASELINE_INTERVAL_CONTAINER_SERIES_KEY))) - .flatMap(field -> this.flattenAggregationsForSeries(attribute, field)); + .flatMap(field -> this.flattenAggregationsForSeries(attributeExpression, field)); } private Observable flattenAggregationsForSeries( - AttributeModel attribute, SelectedField seriesField) { + AttributeAssociation attributeExpression, SelectedField seriesField) { Duration period = this.buildSeriesPeriod(seriesField); return this.aggregationRequestBuilder - .build(attribute, seriesField) + .build(attributeExpression, seriesField) .map(aggregation -> new DefaultMetricSeriesRequest(aggregation, period)); } diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/schema/MetricAggregationQueryable.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/schema/MetricAggregationQueryable.java index a1207eb3..81596f0a 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/schema/MetricAggregationQueryable.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/schema/MetricAggregationQueryable.java @@ -1,8 +1,13 @@ package org.hypertrace.graphql.metric.schema; +import static java.util.Objects.requireNonNull; + import graphql.annotations.annotationTypes.GraphQLField; import graphql.annotations.annotationTypes.GraphQLName; import graphql.annotations.annotationTypes.GraphQLNonNull; +import java.util.Optional; +import javax.annotation.Nullable; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.graphql.metric.schema.argument.MetricKeyArgument; public interface MetricAggregationQueryable { @@ -11,6 +16,13 @@ public interface MetricAggregationQueryable { @GraphQLField @GraphQLName(METRIC_FIELD_NAME) @GraphQLNonNull - BaselinedMetricAggregationContainer metric( - @GraphQLName(MetricKeyArgument.ARGUMENT_NAME) @GraphQLNonNull String key); + default BaselinedMetricAggregationContainer metric( + @GraphQLName(MetricKeyArgument.ARGUMENT_NAME) @Nullable String key, + @GraphQLName(AttributeExpression.ARGUMENT_NAME) @Nullable AttributeExpression expression) { + return metric( + Optional.ofNullable(expression) + .orElseGet(() -> AttributeExpression.forAttributeKey(requireNonNull(key)))); + } + + BaselinedMetricAggregationContainer metric(AttributeExpression attributeExpression); } diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/schema/MetricQueryable.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/schema/MetricQueryable.java index 1872199a..19ec6f9a 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/schema/MetricQueryable.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/schema/MetricQueryable.java @@ -1,8 +1,13 @@ package org.hypertrace.graphql.metric.schema; +import static java.util.Objects.requireNonNull; + import graphql.annotations.annotationTypes.GraphQLField; import graphql.annotations.annotationTypes.GraphQLName; import graphql.annotations.annotationTypes.GraphQLNonNull; +import java.util.Optional; +import javax.annotation.Nullable; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.graphql.metric.schema.argument.MetricKeyArgument; public interface MetricQueryable extends MetricAggregationQueryable { @@ -10,5 +15,14 @@ public interface MetricQueryable extends MetricAggregationQueryable { @GraphQLName(METRIC_FIELD_NAME) @GraphQLNonNull @Override - MetricContainer metric(@GraphQLName(MetricKeyArgument.ARGUMENT_NAME) @GraphQLNonNull String key); + default MetricContainer metric( + @GraphQLName(MetricKeyArgument.ARGUMENT_NAME) @Nullable String key, + @GraphQLName(AttributeExpression.ARGUMENT_NAME) @Nullable AttributeExpression expression) { + return metric( + Optional.ofNullable(expression) + .orElseGet(() -> AttributeExpression.forAttributeKey(requireNonNull(key)))); + } + + @Override + MetricContainer metric(AttributeExpression attributeExpression); } diff --git a/hypertrace-graphql-spaces-schema/src/main/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDao.java b/hypertrace-graphql-spaces-schema/src/main/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDao.java index 87cadd44..3c3eeeb1 100644 --- a/hypertrace-graphql-spaces-schema/src/main/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDao.java +++ b/hypertrace-graphql-spaces-schema/src/main/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDao.java @@ -23,6 +23,7 @@ import org.hypertrace.core.graphql.common.request.AttributeRequestBuilder; import org.hypertrace.core.graphql.common.schema.arguments.TimeRangeArgument; import org.hypertrace.core.graphql.common.schema.attributes.MetricAggregationType; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterArgument; import org.hypertrace.core.graphql.common.schema.results.arguments.order.OrderDirection; import org.hypertrace.core.graphql.context.GraphQlRequestContext; @@ -66,10 +67,10 @@ public Single getAllSpaces(GraphQlRequestContext context) { private Single buildRequest(GraphQlRequestContext context) { return this.attributeRequestBuilder - .buildForKey( + .buildForAttributeExpression( context, ActiveSpaceExploreRequest.SPACE_IDS_SCOPE, - ActiveSpaceExploreRequest.SPACE_IDS_KEY) + ActiveSpaceExploreRequest.SPACE_IDS_EXPRESSION) .map( attributeRequest -> new ActiveSpaceExploreRequest( @@ -77,7 +78,7 @@ private Single buildRequest(GraphQlRequestContext context) { new FixedTimeRange(this.clock.instant()), attributeRequest, this.metricAggregationRequestBuilder.build( - attributeRequest.attribute(), + attributeRequest.attributeExpression(), AttributeModelMetricAggregationType.COUNT, emptyList()))); } @@ -91,8 +92,8 @@ private SpaceResultSet extractResult(ExploreResultSet exploreResultSet) { exploreResult .selectionMap() .get( - ExploreResultMapKey.basicAttribute( - ActiveSpaceExploreRequest.SPACE_IDS_KEY))) + ExploreResultMapKey.attribute( + ActiveSpaceExploreRequest.SPACE_IDS_EXPRESSION))) .map(Selection::value) .filter(Objects::nonNull) .flatMap( @@ -136,7 +137,8 @@ public Instant startTime() { @Value @Accessors(fluent = true) private static class ActiveSpaceExploreRequest implements ExploreRequest { - private static final String SPACE_IDS_KEY = "spaceIds"; + private static final AttributeExpression SPACE_IDS_EXPRESSION = + AttributeExpression.forAttributeKey("spaceIds"); private static final String SPACE_IDS_SCOPE = "EVENT"; private static final int MAX_SPACES = 100; @@ -166,7 +168,9 @@ private static class ActiveSpaceExploreRequest implements ExploreRequest { // Aggregation needed to pass explorer validation - a no agg request is not valid this.aggregationRequests = Set.of(spaceIdCountRequest); this.orderArguments = - List.of(new SpaceExploreOrderArgument(Optional.of(spaceIdRequest.attribute()))); + List.of( + new SpaceExploreOrderArgument( + Optional.of(spaceIdRequest.attributeExpression().attribute()))); this.groupByAttributeRequests = Set.of(spaceIdRequest); } } @@ -182,7 +186,8 @@ private static class SpaceExploreOrderArgument implements ExploreOrderArgument { @Accessors(fluent = true) private static class SpaceOrderArgument implements AggregatableOrderArgument { OrderDirection direction = OrderDirection.ASC; - String key = ActiveSpaceExploreRequest.SPACE_IDS_KEY; + String key = null; + AttributeExpression keyExpression = ActiveSpaceExploreRequest.SPACE_IDS_EXPRESSION; MetricAggregationType aggregation = null; Integer size = null; } diff --git a/hypertrace-graphql-spaces-schema/src/test/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDaoTest.java b/hypertrace-graphql-spaces-schema/src/test/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDaoTest.java index ed60c702..8aaccce3 100644 --- a/hypertrace-graphql-spaces-schema/src/test/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDaoTest.java +++ b/hypertrace-graphql-spaces-schema/src/test/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDaoTest.java @@ -19,8 +19,10 @@ import java.util.stream.Collectors; import org.hypertrace.core.graphql.attributes.AttributeModel; import org.hypertrace.core.graphql.attributes.AttributeModelMetricAggregationType; +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.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.context.GraphQlRequestContext; import org.hypertrace.graphql.explorer.dao.ExplorerDao; import org.hypertrace.graphql.explorer.fetcher.ExploreResultMapKey; @@ -47,6 +49,8 @@ class ExplorerBackedSpacesDaoTest { @Mock MetricAggregationRequest mockSpaceCountRequest; @Mock Clock mockClock; + final AttributeExpression spaceIdExpression = AttributeExpression.forAttributeKey("spaceIds"); + Instant mockEndTime = Instant.parse("2021-02-01T00:00:00.00Z"); ExplorerBackedSpacesDao dao; @@ -62,13 +66,19 @@ void beforeEach() { when(this.mockClock.instant()).thenReturn(this.mockEndTime); - when(this.mockSpaceAttributeRequest.attribute()).thenReturn(this.mockAttribute); + AttributeAssociation mockExpressionAssociation = + AttributeAssociation.of(mockAttribute, spaceIdExpression); + when(this.mockSpaceAttributeRequest.attributeExpression()) + .thenReturn(mockExpressionAssociation); - when(this.mockAttributeRequestBuilder.buildForKey(this.mockContext, "EVENT", "spaceIds")) + when(this.mockAttributeRequestBuilder.buildForAttributeExpression( + this.mockContext, "EVENT", this.spaceIdExpression)) .thenReturn(Single.just(this.mockSpaceAttributeRequest)); when(this.mockMetricRequestBuilder.build( - this.mockAttribute, AttributeModelMetricAggregationType.COUNT, Collections.emptyList())) + mockExpressionAssociation, + AttributeModelMetricAggregationType.COUNT, + Collections.emptyList())) .thenReturn(this.mockSpaceCountRequest); } @@ -97,7 +107,12 @@ void makesAppropriateRequest() { .get(0) .attribute() .equals(Optional.of(this.mockAttribute)) - && request.orderArguments().get(0).argument().key().equals("spaceIds") + && request + .orderArguments() + .get(0) + .argument() + .resolvedKeyExpression() + .equals(this.spaceIdExpression) && request.orderArguments().get(0).argument().direction().equals(ASC) && request.filterArguments().isEmpty() && request @@ -136,7 +151,7 @@ private ExploreResult buildMockResult(String spaceName) { Selection mockSelection = mock(Selection.class); when(mockSelection.value()).thenReturn(List.of(spaceName)); when(mockResult.selectionMap()) - .thenReturn(Map.of(ExploreResultMapKey.basicAttribute("spaceIds"), mockSelection)); + .thenReturn(Map.of(ExploreResultMapKey.attribute(this.spaceIdExpression), mockSelection)); return mockResult; } } From 5335c6394417aa4a14bc331855f1c09f764ad93f Mon Sep 17 00:00:00 2001 From: Aaron Steinfeld Date: Fri, 17 Dec 2021 10:00:06 -0500 Subject: [PATCH 2/7] chore: temp for testing --- hypertrace-core-graphql | 2 +- .../hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java | 3 +++ .../gateway/BaselinedMetricAggregationMapConverter.java | 3 +++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/hypertrace-core-graphql b/hypertrace-core-graphql index 127dbcb6..479e8970 160000 --- a/hypertrace-core-graphql +++ b/hypertrace-core-graphql @@ -1 +1 @@ -Subproject commit 127dbcb6e3c7d5f59671027acb51755e186d8085 +Subproject commit 479e8970a9a95f4c268b59d5ed52bfb86929bab8 diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java index 9211674e..17174ce0 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java @@ -2,6 +2,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; +import com.google.protobuf.util.JsonFormat; import io.grpc.CallCredentials; import io.reactivex.rxjava3.core.Scheduler; import io.reactivex.rxjava3.core.Single; @@ -75,6 +76,7 @@ public Single getEntities(EntityRequest request) { GraphQlRequestContext context = request.resultSetRequest().context(); return this.requestBuilder .buildRequest(request) + .doOnSuccess(built -> log.warn(JsonFormat.printer().print(built))) .subscribeOn(this.boundedIoScheduler) .flatMap(serverRequest -> this.fetchAndMapEntities(context, request, serverRequest)); } @@ -82,6 +84,7 @@ public Single getEntities(EntityRequest request) { private Single fetchAndMapEntities( GraphQlRequestContext context, EntityRequest request, EntitiesRequest serverRequest) { return this.makeEntityRequest(context, serverRequest) + .doOnSuccess(built -> log.warn(JsonFormat.printer().print(built))) .flatMap(serverResponse -> this.getEntityResultSet(request, serverRequest, serverResponse)); } diff --git a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/BaselinedMetricAggregationMapConverter.java b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/BaselinedMetricAggregationMapConverter.java index b9a91267..eb0b2eb0 100644 --- a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/BaselinedMetricAggregationMapConverter.java +++ b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/BaselinedMetricAggregationMapConverter.java @@ -11,6 +11,7 @@ import javax.inject.Inject; import lombok.Value; import lombok.experimental.Accessors; +import lombok.extern.slf4j.Slf4j; import org.hypertrace.core.graphql.common.utils.TriConverter; import org.hypertrace.gateway.service.v1.baseline.Baseline; import org.hypertrace.gateway.service.v1.common.AggregatedMetricValue; @@ -18,6 +19,7 @@ import org.hypertrace.graphql.metric.schema.BaselinedMetricAggregation; import org.hypertrace.graphql.metric.schema.MetricBaselineAggregation; +@Slf4j class BaselinedMetricAggregationMapConverter implements TriConverter< List, @@ -42,6 +44,7 @@ public Single> convert( Map resultMap, Map baselineMap) { return Observable.fromIterable(aggregationRequests) + .distinct() .flatMapSingle( aggregationRequest -> this.buildMetricAggregationEntry(aggregationRequest, resultMap, baselineMap)) From 614b9a53b157a26913a58df2ace2e5c741239ea5 Mon Sep 17 00:00:00 2001 From: Aaron Steinfeld Date: Thu, 6 Jan 2022 20:12:04 -0500 Subject: [PATCH 3/7] chore: update new label code for attribute expressions --- .snyk | 2 +- .../hypertrace/graphql/label/dao/LabelResponseConverter.java | 5 +++-- .../label/joiner/DefaultEntityAndRuleJoinerBuilder.java | 4 +++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.snyk b/.snyk index 1e9092fa..154d7794 100644 --- a/.snyk +++ b/.snyk @@ -5,6 +5,6 @@ ignore: SNYK-JAVA-IONETTY-1042268: - '*': reason: No replacement available - expires: 2021-12-31T00:00:00.000Z + expires: 2022-03-31T00:00:00.000Z patch: {} diff --git a/hypertrace-graphql-labels-schema-impl/src/main/java/org/hypertrace/graphql/label/dao/LabelResponseConverter.java b/hypertrace-graphql-labels-schema-impl/src/main/java/org/hypertrace/graphql/label/dao/LabelResponseConverter.java index 5b82749b..1f930256 100644 --- a/hypertrace-graphql-labels-schema-impl/src/main/java/org/hypertrace/graphql/label/dao/LabelResponseConverter.java +++ b/hypertrace-graphql-labels-schema-impl/src/main/java/org/hypertrace/graphql/label/dao/LabelResponseConverter.java @@ -7,6 +7,7 @@ import java.util.stream.Collectors; import lombok.Value; import lombok.experimental.Accessors; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.utils.CollectorUtils; import org.hypertrace.graphql.entity.schema.Entity; import org.hypertrace.graphql.entity.schema.EntityResultSet; @@ -137,8 +138,8 @@ public String id() { } @Override - public Object attribute(String key) { - return this.entity.attribute(key); + public Object attribute(AttributeExpression attributeExpression) { + return this.entity.attribute(attributeExpression); } } } diff --git a/hypertrace-graphql-labels-schema-impl/src/main/java/org/hypertrace/graphql/label/joiner/DefaultEntityAndRuleJoinerBuilder.java b/hypertrace-graphql-labels-schema-impl/src/main/java/org/hypertrace/graphql/label/joiner/DefaultEntityAndRuleJoinerBuilder.java index a569781c..b2fbdddd 100644 --- a/hypertrace-graphql-labels-schema-impl/src/main/java/org/hypertrace/graphql/label/joiner/DefaultEntityAndRuleJoinerBuilder.java +++ b/hypertrace-graphql-labels-schema-impl/src/main/java/org/hypertrace/graphql/label/joiner/DefaultEntityAndRuleJoinerBuilder.java @@ -31,6 +31,7 @@ import org.hypertrace.core.graphql.common.request.ResultSetRequestBuilder; import org.hypertrace.core.graphql.common.schema.arguments.TimeRangeArgument; import org.hypertrace.core.graphql.common.schema.attributes.AttributeScope; +import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; import org.hypertrace.core.graphql.common.schema.results.ResultSet; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterArgument; import org.hypertrace.core.graphql.common.schema.results.arguments.filter.FilterOperatorType; @@ -342,7 +343,8 @@ private static class InstantTimeRange implements TimeRangeArgument { @Accessors(fluent = true) private static class LabelIdFilter implements FilterArgument { FilterType type = FilterType.ATTRIBUTE; - String key = "labels"; + String key = null; + AttributeExpression keyExpression = AttributeExpression.forAttributeKey("labels"); FilterOperatorType operator = FilterOperatorType.EQUALS; String value; AttributeScope idType = null; From 19c026a4ecb20a743933c98b74addeae766ff5f1 Mon Sep 17 00:00:00 2001 From: Aaron Steinfeld Date: Fri, 7 Jan 2022 08:17:36 -0500 Subject: [PATCH 4/7] chore: update submodule --- hypertrace-core-graphql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hypertrace-core-graphql b/hypertrace-core-graphql index af5b41e2..7be2e988 160000 --- a/hypertrace-core-graphql +++ b/hypertrace-core-graphql @@ -1 +1 @@ -Subproject commit af5b41e2f4002440b3f264564801ee2caed34a22 +Subproject commit 7be2e988f23284b99fcf9854245402e3b6bff635 From f0bfa9d9e8a0fee42121ce0be54a8102918af32f Mon Sep 17 00:00:00 2001 From: Aaron Steinfeld Date: Fri, 7 Jan 2022 12:09:35 -0500 Subject: [PATCH 5/7] fix: remove debug logging --- .../hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java index 17174ce0..74a8a604 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java @@ -76,7 +76,6 @@ public Single getEntities(EntityRequest request) { GraphQlRequestContext context = request.resultSetRequest().context(); return this.requestBuilder .buildRequest(request) - .doOnSuccess(built -> log.warn(JsonFormat.printer().print(built))) .subscribeOn(this.boundedIoScheduler) .flatMap(serverRequest -> this.fetchAndMapEntities(context, request, serverRequest)); } @@ -84,7 +83,6 @@ public Single getEntities(EntityRequest request) { private Single fetchAndMapEntities( GraphQlRequestContext context, EntityRequest request, EntitiesRequest serverRequest) { return this.makeEntityRequest(context, serverRequest) - .doOnSuccess(built -> log.warn(JsonFormat.printer().print(built))) .flatMap(serverResponse -> this.getEntityResultSet(request, serverRequest, serverResponse)); } From 08d7619521e4db671a15dc04ace725f7bdf20fc2 Mon Sep 17 00:00:00 2001 From: Aaron Steinfeld Date: Fri, 7 Jan 2022 12:13:46 -0500 Subject: [PATCH 6/7] style: spotless --- .../hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java | 1 - 1 file changed, 1 deletion(-) diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java index 74a8a604..9211674e 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityDao.java @@ -2,7 +2,6 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; -import com.google.protobuf.util.JsonFormat; import io.grpc.CallCredentials; import io.reactivex.rxjava3.core.Scheduler; import io.reactivex.rxjava3.core.Single; From 7fea23a385b81662f094fbc4f8c262fae2f14119 Mon Sep 17 00:00:00 2001 From: Aaron Steinfeld Date: Sun, 9 Jan 2022 10:25:50 -0500 Subject: [PATCH 7/7] chore: rename attribute expression association --- hypertrace-core-graphql | 2 +- .../dao/GatewayServiceEntityConverter.java | 2 +- ...erviceEntityInteractionRequestBuilder.java | 4 +-- .../GatewayServiceSelectionMapConverter.java | 10 +++++--- .../explorer/fetcher/ExploreResultMapKey.java | 2 +- ...gatableOrderByExpressionListConverter.java | 12 ++++----- ...etricAggregationContainerMapConverter.java | 2 +- .../MetricAggregationExpressionConverter.java | 15 +++++------ .../gateway/MetricContainerMapConverter.java | 2 +- ...efaultMetricAggregationRequestBuilder.java | 25 +++++++++++-------- .../request/DefaultMetricRequestBuilder.java | 12 ++++----- .../request/MetricAggregationRequest.java | 2 +- .../MetricAggregationRequestBuilder.java | 4 +-- .../graphql/metric/request/MetricRequest.java | 2 +- .../request/MetricSeriesRequestBuilder.java | 13 +++++----- .../spaces/dao/ExplorerBackedSpacesDao.java | 4 +-- .../dao/ExplorerBackedSpacesDaoTest.java | 2 +- 17 files changed, 63 insertions(+), 52 deletions(-) diff --git a/hypertrace-core-graphql b/hypertrace-core-graphql index 7be2e988..43f084b8 160000 --- a/hypertrace-core-graphql +++ b/hypertrace-core-graphql @@ -1 +1 @@ -Subproject commit 7be2e988f23284b99fcf9854245402e3b6bff635 +Subproject commit 43f084b878511945a90c64065ed8024124b62769 diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityConverter.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityConverter.java index c4b124aa..c8b5d183 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityConverter.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityConverter.java @@ -129,7 +129,7 @@ private Single convertEntity( entityRequest .resultSetRequest() .idAttribute() - .attributeExpression() + .attributeExpressionAssociation() .value()) .toString(), entityRequest.entityType(), diff --git a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityInteractionRequestBuilder.java b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityInteractionRequestBuilder.java index d83fc57d..777344b4 100644 --- a/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityInteractionRequestBuilder.java +++ b/hypertrace-graphql-entity-schema/src/main/java/org/hypertrace/graphql/entity/dao/GatewayServiceEntityInteractionRequestBuilder.java @@ -72,9 +72,9 @@ private Single buildEntityTypeFilter(EdgeSetGroupRequest request) { .map( entityTypes -> AttributeAssociation.of( - request.neighborTypeAttribute().attributeExpression().attribute(), + request.neighborTypeAttribute().attributeExpressionAssociation().attribute(), new EntityNeighborTypeFilter( - request.neighborTypeAttribute().attributeExpression().value(), + request.neighborTypeAttribute().attributeExpressionAssociation().value(), entityTypes))) .flatMap(filterAssociation -> this.filterConverter.convert(Set.of(filterAssociation))); } diff --git a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/dao/GatewayServiceSelectionMapConverter.java b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/dao/GatewayServiceSelectionMapConverter.java index 4c3598fe..d5b19ade 100644 --- a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/dao/GatewayServiceSelectionMapConverter.java +++ b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/dao/GatewayServiceSelectionMapConverter.java @@ -69,11 +69,14 @@ private Single> buildAttributeMapEntry( return this.valueConverter .convert(row.getColumnsOrThrow(attributeRequest.asMapKey())) .flatMap( - value -> this.buildSelection(attributeRequest.attributeExpression().attribute(), value)) + value -> + this.buildSelection( + attributeRequest.attributeExpressionAssociation().attribute(), value)) .map( selection -> Map.entry( - ExploreResultMapKey.attribute(attributeRequest.attributeExpression().value()), + ExploreResultMapKey.attribute( + attributeRequest.attributeExpressionAssociation().value()), selection)); } @@ -90,7 +93,8 @@ private Single> buildAggregationMapEntry( .convert(row.getColumnsOrThrow(aggregationRequest.alias())) .flatMap( value -> - this.buildSelection(aggregationRequest.attributeExpression().attribute(), value)) + this.buildSelection( + aggregationRequest.attributeExpressionAssociation().attribute(), value)) .zipWith( this.aggregationTypeConverter.convert(aggregationRequest.aggregation()), (selection, aggregation) -> diff --git a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/fetcher/ExploreResultMapKey.java b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/fetcher/ExploreResultMapKey.java index 665a906c..a7ae3216 100644 --- a/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/fetcher/ExploreResultMapKey.java +++ b/hypertrace-graphql-explorer-schema/src/main/java/org/hypertrace/graphql/explorer/fetcher/ExploreResultMapKey.java @@ -30,7 +30,7 @@ public static ExploreResultMapKey attribute(AttributeExpression attributeExpress public static ExploreResultMapKey forAggregationRequest( MetricAggregationRequest aggregationRequest, MetricAggregationType aggregationType) { return new ExploreResultMapKey( - aggregationRequest.attributeExpression().value(), + aggregationRequest.attributeExpressionAssociation().value(), aggregationType, aggregationRequest.arguments()); } diff --git a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/AggregatableOrderByExpressionListConverter.java b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/AggregatableOrderByExpressionListConverter.java index 4c2cf956..5790c6a7 100644 --- a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/AggregatableOrderByExpressionListConverter.java +++ b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/AggregatableOrderByExpressionListConverter.java @@ -64,23 +64,23 @@ private Single buildOrderByExpression( private Single buildSelectionExpression( AttributeAssociation orderArgument) { - AttributeAssociation attributeExpression = - this.buildAttributeExpression(orderArgument); + AttributeAssociation attributeExpressionAssociation = + this.buildAttributeExpressionAssociation(orderArgument); return Maybe.fromOptional(Optional.ofNullable(orderArgument.value().aggregation())) .flatMapSingle(this.aggregationTypeConverter::convert) .flatMapSingle( aggregationType -> orderArgument.value().size() == null ? this.metricAggregationExpressionConverter.convertForNoArgsOrAlias( - attributeExpression, aggregationType) + attributeExpressionAssociation, aggregationType) : this.metricAggregationExpressionConverter.convertForArgsButNoAlias( - attributeExpression, + attributeExpressionAssociation, aggregationType, List.of(Objects.requireNonNull(orderArgument.value().size())))) - .switchIfEmpty(this.columnExpressionConverter.convert(attributeExpression)); + .switchIfEmpty(this.columnExpressionConverter.convert(attributeExpressionAssociation)); } - private AttributeAssociation buildAttributeExpression( + private AttributeAssociation buildAttributeExpressionAssociation( AttributeAssociation orderArgumentAttributeAssociation) { return AttributeAssociation.of( orderArgumentAttributeAssociation.attribute(), diff --git a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationContainerMapConverter.java b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationContainerMapConverter.java index 91e2bfbc..bb404c3c 100644 --- a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationContainerMapConverter.java +++ b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationContainerMapConverter.java @@ -36,7 +36,7 @@ public Single> con Map metricResponses) { return Observable.fromIterable(metricRequests) .distinct() - .groupBy(request -> request.attributeExpression().value()) + .groupBy(request -> request.attributeExpressionAssociation().value()) .flatMapSingle(requests -> this.buildMetricContainerEntry(requests, metricResponses)) .collect(immutableMapEntryCollector()); } diff --git a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationExpressionConverter.java b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationExpressionConverter.java index 74ef6c74..04828c49 100644 --- a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationExpressionConverter.java +++ b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricAggregationExpressionConverter.java @@ -45,7 +45,7 @@ public Single> convert(Collection metr Single convert(MetricAggregationRequest metricAggregation, String alias) { return this.buildAggregationFunctionExpression( - metricAggregation.attributeExpression(), + metricAggregation.attributeExpressionAssociation(), metricAggregation.aggregation(), metricAggregation.arguments(), alias) @@ -53,17 +53,18 @@ Single convert(MetricAggregationRequest metricAggregation, String al } Single convertForNoArgsOrAlias( - AttributeAssociation attributeExpression, + AttributeAssociation attributeExpressionAssociation, AttributeModelMetricAggregationType aggregationType) { - return convertForArgsButNoAlias(attributeExpression, aggregationType, Collections.emptyList()); + return convertForArgsButNoAlias( + attributeExpressionAssociation, aggregationType, Collections.emptyList()); } Single convertForArgsButNoAlias( - AttributeAssociation attributeExpression, + AttributeAssociation attributeExpressionAssociation, AttributeModelMetricAggregationType aggregationType, List arguments) { return this.buildAggregationFunctionExpression( - attributeExpression, + attributeExpressionAssociation, aggregationType, arguments, StringValue.getDefaultInstance().getValue()) @@ -71,13 +72,13 @@ Single convertForArgsButNoAlias( } private Single buildAggregationFunctionExpression( - AttributeAssociation attributeExpression, + AttributeAssociation attributeExpressionAssociation, AttributeModelMetricAggregationType aggregationType, List arguments, String alias) { return zip( functionTypeConverter.convert(aggregationType), - this.columnExpressionConverter.convert(attributeExpression), + this.columnExpressionConverter.convert(attributeExpressionAssociation), this.convertArguments(arguments), (functionType, columnExpression, argumentExpressionList) -> FunctionExpression.newBuilder() diff --git a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricContainerMapConverter.java b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricContainerMapConverter.java index 72853731..3859b75b 100644 --- a/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricContainerMapConverter.java +++ b/hypertrace-graphql-gateway-service-metric-utils/src/main/java/org/hypertrace/graphql/utils/metrics/gateway/MetricContainerMapConverter.java @@ -53,7 +53,7 @@ public Single> convert( Collection metricRequests, Entity entity, BaselineEntity baselineEntity) { return Observable.fromIterable(metricRequests) .distinct() - .groupBy(request -> request.attributeExpression().value()) + .groupBy(request -> request.attributeExpressionAssociation().value()) .flatMapSingle(requests -> this.buildMetricContainerEntry(requests, entity, baselineEntity)) .collect(immutableMapEntryCollector()); } diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricAggregationRequestBuilder.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricAggregationRequestBuilder.java index d208490b..04b764e4 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricAggregationRequestBuilder.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricAggregationRequestBuilder.java @@ -53,7 +53,7 @@ class DefaultMetricAggregationRequestBuilder implements MetricAggregationRequest @Override public Observable build( - AttributeAssociation attributeExpression, + AttributeAssociation attributeExpressionAssociation, SelectedField metricAggregationContainerField) { return Observable.fromStream( this.selectionFinder.findSelections( @@ -61,7 +61,9 @@ public Observable build( SelectionQuery.builder() .matchesPredicate(field -> this.getAggregationTypeForField(field).isPresent()) .build())) - .map(selectedField -> this.requestForAggregationField(attributeExpression, selectedField)); + .map( + selectedField -> + this.requestForAggregationField(attributeExpressionAssociation, selectedField)); } @Override @@ -74,27 +76,28 @@ public Single> build( } public MetricAggregationRequest build( - AttributeAssociation attributeExpression, + AttributeAssociation attributeExpressionAssociation, AttributeModelMetricAggregationType aggregationType, List arguments) { - return this.build(attributeExpression, aggregationType, arguments, false); + return this.build(attributeExpressionAssociation, aggregationType, arguments, false); } private MetricAggregationRequest build( - AttributeAssociation attributeExpression, + AttributeAssociation attributeExpressionAssociation, AttributeModelMetricAggregationType aggregationType, List arguments, boolean baseline) { return new DefaultMetricAggregationRequest( - attributeExpression, aggregationType, arguments, baseline); + attributeExpressionAssociation, aggregationType, arguments, baseline); } private MetricAggregationRequest requestForAggregationField( - AttributeAssociation attributeExpression, SelectedField field) { + AttributeAssociation attributeExpressionAssociation, + SelectedField field) { AttributeModelMetricAggregationType aggregationType = this.getAggregationTypeForField(field).orElseThrow(); return this.build( - attributeExpression, + attributeExpressionAssociation, aggregationType, this.getArgumentsForAggregation(aggregationType, field.getArguments()), this.selectionFinder @@ -170,7 +173,7 @@ private Integer percentileSize(Map arguments) { @Value @Accessors(fluent = true) private static class DefaultMetricAggregationRequest implements MetricAggregationRequest { - AttributeAssociation attributeExpression; + AttributeAssociation attributeExpressionAssociation; AttributeModelMetricAggregationType aggregation; List arguments; boolean baseline; @@ -179,7 +182,9 @@ private static class DefaultMetricAggregationRequest implements MetricAggregatio public String alias() { return String.format( "%s_%s_%s", - this.aggregation.name(), this.attributeExpression.attribute().id(), this.arguments); + this.aggregation.name(), + this.attributeExpressionAssociation.attribute().id(), + this.arguments); } @Override diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricRequestBuilder.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricRequestBuilder.java index 5c22ee43..ce89f3f5 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricRequestBuilder.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/DefaultMetricRequestBuilder.java @@ -39,21 +39,21 @@ public Single> build( } private Observable collectAggregationsAndSeries( - AttributeAssociation attributeExpression, + AttributeAssociation attributeExpressionAssociation, SelectedField metricContainerField) { return Single.zip( this.aggregationRequestBuilder - .build(attributeExpression, metricContainerField) + .build(attributeExpressionAssociation, metricContainerField) .collect(Collectors.toUnmodifiableList()), this.seriesRequestBuilder - .build(attributeExpression, metricContainerField) + .build(attributeExpressionAssociation, metricContainerField) .collect(Collectors.toUnmodifiableList()), this.seriesRequestBuilder - .buildBaselineSeriesRequests(attributeExpression, metricContainerField) + .buildBaselineSeriesRequests(attributeExpressionAssociation, metricContainerField) .collect(Collectors.toUnmodifiableList()), (aggList, seriesList, baselineSeriesList) -> new DefaultMetricRequest( - attributeExpression, aggList, seriesList, baselineSeriesList)) + attributeExpressionAssociation, aggList, seriesList, baselineSeriesList)) .cast(MetricRequest.class) .toObservable(); } @@ -61,7 +61,7 @@ private Observable collectAggregationsAndSeries( @Value @Accessors(fluent = true) private static class DefaultMetricRequest implements MetricRequest { - AttributeAssociation attributeExpression; + AttributeAssociation attributeExpressionAssociation; List aggregationRequests; List seriesRequests; List baselineSeriesRequests; diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequest.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequest.java index 001434c7..f54c8223 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequest.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequest.java @@ -7,7 +7,7 @@ public interface MetricAggregationRequest { - AttributeAssociation attributeExpression(); + AttributeAssociation attributeExpressionAssociation(); AttributeModelMetricAggregationType aggregation(); diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequestBuilder.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequestBuilder.java index 8ff316a1..fb7705be 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequestBuilder.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricAggregationRequestBuilder.java @@ -12,7 +12,7 @@ public interface MetricAggregationRequestBuilder { Observable build( - AttributeAssociation attributeExpression, + AttributeAssociation attributeExpressionAssociation, SelectedField metricAggregationContainerField); Single> build( @@ -21,7 +21,7 @@ Single> build( Stream metricQueryableFieldStream); MetricAggregationRequest build( - AttributeAssociation attributeExpression, + AttributeAssociation attributeExpressionAssociation, AttributeModelMetricAggregationType aggregationType, List arguments); } diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricRequest.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricRequest.java index a138b3aa..e782942a 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricRequest.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricRequest.java @@ -5,7 +5,7 @@ import org.hypertrace.core.graphql.common.schema.attributes.arguments.AttributeExpression; public interface MetricRequest { - AttributeAssociation attributeExpression(); + AttributeAssociation attributeExpressionAssociation(); List aggregationRequests(); diff --git a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricSeriesRequestBuilder.java b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricSeriesRequestBuilder.java index 93c2174f..188db13d 100644 --- a/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricSeriesRequestBuilder.java +++ b/hypertrace-graphql-metric-schema/src/main/java/org/hypertrace/graphql/metric/request/MetricSeriesRequestBuilder.java @@ -36,30 +36,31 @@ class MetricSeriesRequestBuilder { } Observable build( - AttributeAssociation attributeExpression, + AttributeAssociation attributeExpressionAssociation, SelectedField metricContainerField) { return Observable.fromStream( this.selectionFinder.findSelections( metricContainerField.getSelectionSet(), SelectionQuery.namedChild(METRIC_INTERVAL_CONTAINER_SERIES_KEY))) - .flatMap(field -> this.flattenAggregationsForSeries(attributeExpression, field)); + .flatMap(field -> this.flattenAggregationsForSeries(attributeExpressionAssociation, field)); } Observable buildBaselineSeriesRequests( - AttributeAssociation attributeExpression, + AttributeAssociation attributeExpressionAssociation, SelectedField metricContainerField) { return Observable.fromStream( this.selectionFinder.findSelections( metricContainerField.getSelectionSet(), SelectionQuery.namedChild(BASELINE_INTERVAL_CONTAINER_SERIES_KEY))) - .flatMap(field -> this.flattenAggregationsForSeries(attributeExpression, field)); + .flatMap(field -> this.flattenAggregationsForSeries(attributeExpressionAssociation, field)); } private Observable flattenAggregationsForSeries( - AttributeAssociation attributeExpression, SelectedField seriesField) { + AttributeAssociation attributeExpressionAssociation, + SelectedField seriesField) { Duration period = this.buildSeriesPeriod(seriesField); return this.aggregationRequestBuilder - .build(attributeExpression, seriesField) + .build(attributeExpressionAssociation, seriesField) .map(aggregation -> new DefaultMetricSeriesRequest(aggregation, period)); } diff --git a/hypertrace-graphql-spaces-schema/src/main/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDao.java b/hypertrace-graphql-spaces-schema/src/main/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDao.java index 3c3eeeb1..d08e2674 100644 --- a/hypertrace-graphql-spaces-schema/src/main/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDao.java +++ b/hypertrace-graphql-spaces-schema/src/main/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDao.java @@ -78,7 +78,7 @@ private Single buildRequest(GraphQlRequestContext context) { new FixedTimeRange(this.clock.instant()), attributeRequest, this.metricAggregationRequestBuilder.build( - attributeRequest.attributeExpression(), + attributeRequest.attributeExpressionAssociation(), AttributeModelMetricAggregationType.COUNT, emptyList()))); } @@ -170,7 +170,7 @@ private static class ActiveSpaceExploreRequest implements ExploreRequest { this.orderArguments = List.of( new SpaceExploreOrderArgument( - Optional.of(spaceIdRequest.attributeExpression().attribute()))); + Optional.of(spaceIdRequest.attributeExpressionAssociation().attribute()))); this.groupByAttributeRequests = Set.of(spaceIdRequest); } } diff --git a/hypertrace-graphql-spaces-schema/src/test/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDaoTest.java b/hypertrace-graphql-spaces-schema/src/test/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDaoTest.java index 8aaccce3..88b8536b 100644 --- a/hypertrace-graphql-spaces-schema/src/test/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDaoTest.java +++ b/hypertrace-graphql-spaces-schema/src/test/java/org/hypertrace/graphql/spaces/dao/ExplorerBackedSpacesDaoTest.java @@ -68,7 +68,7 @@ void beforeEach() { AttributeAssociation mockExpressionAssociation = AttributeAssociation.of(mockAttribute, spaceIdExpression); - when(this.mockSpaceAttributeRequest.attributeExpression()) + when(this.mockSpaceAttributeRequest.attributeExpressionAssociation()) .thenReturn(mockExpressionAssociation); when(this.mockAttributeRequestBuilder.buildForAttributeExpression(