diff --git a/gateway-service-api/build.gradle.kts b/gateway-service-api/build.gradle.kts index 0d07aa9f..88b8bd13 100644 --- a/gateway-service-api/build.gradle.kts +++ b/gateway-service-api/build.gradle.kts @@ -22,7 +22,7 @@ protobuf { // the identifier, which can be referred to in the "plugins" // container of the "generateProtoTasks" closure. id("grpc_java") { - artifact = "io.grpc:protoc-gen-grpc-java:1.42.0" + artifact = "io.grpc:protoc-gen-grpc-java:1.43.1" } } generateProtoTasks { @@ -47,9 +47,9 @@ sourceSets { } dependencies { - api("io.grpc:grpc-protobuf:1.42.0") + api("io.grpc:grpc-protobuf:1.43.1") api("com.google.api.grpc:proto-google-common-protos:2.3.2") - api("io.grpc:grpc-stub:1.42.0") + api("io.grpc:grpc-stub:1.43.1") api("javax.annotation:javax.annotation-api:1.3.2") constraints { diff --git a/gateway-service-api/src/main/proto/org/hypertrace/gateway/service/v1/gateway_query.proto b/gateway-service-api/src/main/proto/org/hypertrace/gateway/service/v1/gateway_query.proto index 3e4a3edb..a9cc966b 100644 --- a/gateway-service-api/src/main/proto/org/hypertrace/gateway/service/v1/gateway_query.proto +++ b/gateway-service-api/src/main/proto/org/hypertrace/gateway/service/v1/gateway_query.proto @@ -103,6 +103,7 @@ message Expression { FunctionExpression function = 3; OrderByExpression orderBy = 4; HealthExpression health = 5; + AttributeExpression attribute_expression = 6; } } @@ -181,3 +182,9 @@ message Row { // key is column_name from metadata map columns = 1; } + +message AttributeExpression { + string attributeId = 1; + optional string subpath = 2; + optional string alias = 3; +} diff --git a/gateway-service-impl/build.gradle.kts b/gateway-service-impl/build.gradle.kts index 39bb5935..c7da2a86 100644 --- a/gateway-service-impl/build.gradle.kts +++ b/gateway-service-impl/build.gradle.kts @@ -12,11 +12,11 @@ dependencies { api(project(":gateway-service-api")) api(project(":gateway-service-baseline-lib")) - implementation("org.hypertrace.core.query.service:query-service-client:0.6.2") + implementation("org.hypertrace.core.query.service:query-service-client:0.7.0") implementation("org.hypertrace.core.attribute.service:attribute-service-client:0.12.5") implementation("org.hypertrace.entity.service:entity-service-client:0.8.11") implementation("org.hypertrace.entity.service:entity-service-api:0.8.11") - implementation("org.hypertrace.core.grpcutils:grpc-context-utils:0.6.2") + implementation("org.hypertrace.core.grpcutils:grpc-context-utils:0.7.0") implementation("org.hypertrace.core.serviceframework:platform-metrics:0.1.29") // Config @@ -33,6 +33,6 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter:5.7.0") testImplementation("org.mockito:mockito-core:3.9.0") testImplementation("org.mockito:mockito-inline:3.9.0") - testImplementation("org.apache.logging.log4j:log4j-slf4j-impl:2.17.0") - testImplementation("io.grpc:grpc-netty:1.42.0") + testImplementation("org.apache.logging.log4j:log4j-slf4j-impl:2.17.1") + testImplementation("io.grpc:grpc-netty:1.43.1") } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/GatewayServiceImpl.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/GatewayServiceImpl.java index 02cc65a2..1a178833 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/GatewayServiceImpl.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/GatewayServiceImpl.java @@ -189,9 +189,8 @@ public void getSpans( public void getEntities( org.hypertrace.gateway.service.v1.entity.EntitiesRequest request, StreamObserver responseObserver) { - if (LOG.isDebugEnabled()) { - LOG.debug("Received request: {}", request); - } + + LOG.debug("Received request: {}", request); Optional tenantId = org.hypertrace.core.grpcutils.context.RequestContext.CURRENT.get().getTenantId(); diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/baseline/BaselineServiceQueryParser.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/baseline/BaselineServiceQueryParser.java index f1177691..2753f1a9 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/baseline/BaselineServiceQueryParser.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/baseline/BaselineServiceQueryParser.java @@ -68,7 +68,7 @@ public QueryRequest getQueryRequest( builder.addAllGroupBy( entityIdAttributes.stream() - .map(QueryRequestUtil::createColumnExpression) + .map(QueryRequestUtil::createAttributeExpression) .collect(Collectors.toList())); builder.addGroupBy(createTimeColumnGroupByExpression(timeColumn, periodSecs)); @@ -167,7 +167,7 @@ public BaselineEntitiesResponse parseQueryResponse( Value convertedValue = QueryAndGatewayDtoConverter.convertToGatewayValueForMetricValue( - MetricAggregationFunctionUtil.getValueTypeFromFunction( + MetricAggregationFunctionUtil.getValueTypeForFunctionType( timeAggregation.getAggregation(), attributeMetadataMap), attributeMetadataMap, metadata, diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/QueryRequestContext.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/QueryRequestContext.java index 6c942407..5fe0091a 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/QueryRequestContext.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/QueryRequestContext.java @@ -11,7 +11,7 @@ public class QueryRequestContext extends RequestContext { private final Map aliasToFunctionExpressionMap = new HashMap<>(); private final long startTimeMillis; private final long endTimeMillis; - private final Map aliasToTimeAggregation = new HashMap(); + private final Map aliasToTimeAggregation = new HashMap<>(); public QueryRequestContext( String tenantId, long startTimeMillis, long endTimeMillis, Map headers) { diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/comparators/OrderByComparator.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/comparators/OrderByComparator.java index 9243bc3e..a231671a 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/comparators/OrderByComparator.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/comparators/OrderByComparator.java @@ -2,7 +2,7 @@ import java.util.Comparator; import java.util.List; -import org.hypertrace.gateway.service.common.util.MetricAggregationFunctionUtil; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.v1.common.OrderByExpression; import org.hypertrace.gateway.service.v1.common.SortOrder; @@ -37,28 +37,33 @@ public OrderByComparator(List orderByList) { @Override public int compare(T o1, T o2) { for (OrderByExpression orderBy : orderByList) { - - // Check if we need to order by an aggregated metric. switch (orderBy.getExpression().getValueCase()) { case FUNCTION: - org.hypertrace.gateway.service.v1.common.FunctionExpression function = - orderBy.getExpression().getFunction(); - String alias = MetricAggregationFunctionUtil.getAggregationFunctionAlias(function); - int value = compareFunctionExpressionValues(o1, o2, alias); - if (value == 0) { + int functionComparisonResult = + compareFunctionExpressionValues( + o1, + o2, + ExpressionReader.getSelectionResultName(orderBy.getExpression()).orElseThrow()); + if (functionComparisonResult == 0) { continue; } - return orderBy.getOrder() == SortOrder.ASC ? value : Math.negateExact(value); + return orderBy.getOrder() == SortOrder.ASC + ? functionComparisonResult + : Math.negateExact(functionComparisonResult); case COLUMNIDENTIFIER: - // Otherwise, this is either a simple attribute/metric or entity name itself. - String attr = orderBy.getExpression().getColumnIdentifier().getColumnName(); - value = compareColumnExpressionValues(o1, o2, attr); - if (value == 0) { + case ATTRIBUTE_EXPRESSION: + int selectionComparisonResult = + compareColumnExpressionValues( + o1, + o2, + ExpressionReader.getSelectionResultName(orderBy.getExpression()).orElseThrow()); + if (selectionComparisonResult == 0) { continue; } - return orderBy.getOrder() == SortOrder.ASC ? value : Math.negateExact(value); - + return orderBy.getOrder() == SortOrder.ASC + ? selectionComparisonResult + : Math.negateExact(selectionComparisonResult); default: throw new IllegalArgumentException( "Invalid orderBy: " + orderBy.getExpression().getValueCase()); diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/config/ScopeFilterConfig.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/config/ScopeFilterConfig.java index 7b2c586b..7ed65327 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/config/ScopeFilterConfig.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/config/ScopeFilterConfig.java @@ -4,9 +4,9 @@ public class ScopeFilterConfig { private final String scope; - private final List scopeFilters; + private final List> scopeFilters; - public ScopeFilterConfig(String scope, List scopeFilters) { + public ScopeFilterConfig(String scope, List> scopeFilters) { this.scope = scope; this.scopeFilters = scopeFilters; } @@ -15,7 +15,7 @@ public String getScope() { return scope; } - public List getScopeFilters() { + public List> getScopeFilters() { return scopeFilters; } } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/config/ScopeFilterConfigs.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/config/ScopeFilterConfigs.java index 4eeb4f3b..2d264da8 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/config/ScopeFilterConfigs.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/config/ScopeFilterConfigs.java @@ -8,13 +8,9 @@ import org.hypertrace.core.attribute.service.v1.AttributeMetadata; import org.hypertrace.gateway.service.common.AttributeMetadataProvider; import org.hypertrace.gateway.service.common.RequestContext; -import org.hypertrace.gateway.service.v1.common.ColumnIdentifier; -import org.hypertrace.gateway.service.v1.common.Expression; +import org.hypertrace.gateway.service.common.util.QueryExpressionUtil; import org.hypertrace.gateway.service.v1.common.Filter; -import org.hypertrace.gateway.service.v1.common.LiteralConstant; import org.hypertrace.gateway.service.v1.common.Operator; -import org.hypertrace.gateway.service.v1.common.Value; -import org.hypertrace.gateway.service.v1.common.ValueType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -69,10 +65,10 @@ private void addScopeFilterConfig(Config config) { String attributeScope = config.getString(SCOPE_CONFIG); List filterConfigsList = config.getConfigList(FILTERS_CONFIG); try { - List scopeFilters = + List> scopeFilters = filterConfigsList.stream() .map( - (filterConfig) -> + filterConfig -> new ScopeFilter<>( filterConfig.getString(SCOPE_CONFIG), filterConfig.getString(FILTER_KEY_CONFIG), @@ -119,35 +115,23 @@ private Filter.Builder createScopeFilter( scopeFilterConfig .getScopeFilters() .forEach( - (scopeFilter -> + scopeFilter -> filterBuilder.addChildFilter( createScopeChildFilter( - scopeFilter, attributeMetadataProvider, requestContext)))); + scopeFilter, attributeMetadataProvider, requestContext))); return filterBuilder; } - private Filter.Builder createScopeChildFilter( - ScopeFilter scopeFilter, + private Filter createScopeChildFilter( + ScopeFilter scopeFilter, AttributeMetadataProvider attributeMetadataProvider, RequestContext requestContext) { AttributeMetadata attributeMetadata = attributeMetadataProvider .getAttributeMetadata(requestContext, scopeFilter.getScope(), scopeFilter.getKey()) .orElseThrow(); - return Filter.newBuilder() - .setLhs( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder().setColumnName(attributeMetadata.getId()))) - .setOperator(scopeFilter.getOperator()) - .setRhs( - Expression.newBuilder() - .setLiteral( - LiteralConstant.newBuilder() - .setValue( - Value.newBuilder() - .setValueType(ValueType.STRING) - .setString((String) scopeFilter.getFilterValue())))); + return QueryExpressionUtil.buildStringFilter( + attributeMetadata.getId(), scopeFilter.getOperator(), scopeFilter.getFilterValue()); } } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/converters/EntityServiceAndGatewayServiceConverter.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/converters/EntityServiceAndGatewayServiceConverter.java index 508be05c..765ea86d 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/converters/EntityServiceAndGatewayServiceConverter.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/converters/EntityServiceAndGatewayServiceConverter.java @@ -1,7 +1,6 @@ package org.hypertrace.gateway.service.common.converters; import java.util.List; -import java.util.Map; import java.util.stream.Collectors; import org.hypertrace.core.attribute.service.v1.AttributeMetadata; import org.hypertrace.entity.query.service.v1.BulkEntityArrayAttributeUpdateRequest.Operation; @@ -18,8 +17,10 @@ import org.hypertrace.entity.query.service.v1.ValueType; import org.hypertrace.gateway.service.common.AttributeMetadataProvider; import org.hypertrace.gateway.service.common.util.AttributeMetadataUtil; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.entity.EntitiesRequestContext; import org.hypertrace.gateway.service.entity.config.TimestampConfigs; +import org.hypertrace.gateway.service.v1.common.AttributeExpression; import org.hypertrace.gateway.service.v1.entity.EntitiesRequest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -128,6 +129,10 @@ public static Expression.Builder convertToEntityServiceExpression( builder.setColumnIdentifier( convertToQueryColumnIdentifier(expression.getColumnIdentifier())); break; + case ATTRIBUTE_EXPRESSION: + builder.setColumnIdentifier( + convertToQueryColumnIdentifier(expression.getAttributeExpression())); + break; case FUNCTION: builder.setFunction(convertToQueryFunction(expression.getFunction())); break; @@ -151,6 +156,20 @@ public static ColumnIdentifier.Builder convertToQueryColumnIdentifier( .setAlias(columnIdentifier.getAlias()); } + public static ColumnIdentifier convertToQueryColumnIdentifier( + AttributeExpression attributeExpression) { + if (attributeExpression.hasSubpath()) { + throw new IllegalArgumentException( + "Attribute expression with subpath not supported by entity service " + + attributeExpression.toString()); + } + + return ColumnIdentifier.newBuilder() + .setColumnName(attributeExpression.getAttributeId()) + .setAlias(attributeExpression.getAlias()) + .build(); + } + public static LiteralConstant convertToQueryLiteral( org.hypertrace.gateway.service.v1.common.LiteralConstant literal) { return LiteralConstant.newBuilder() @@ -186,7 +205,7 @@ private static Function convertToQueryFunction( // percentile. List columns = function.getArgumentsList().stream() - .filter(org.hypertrace.gateway.service.v1.common.Expression::hasColumnIdentifier) + .filter(ExpressionReader::isAttributeSelection) .collect(Collectors.toList()); columns.forEach(e -> builder.addArguments(convertToEntityServiceExpression(e))); break; @@ -284,16 +303,6 @@ public static Expression.Builder createColumnExpression(String columnName) { .setColumnIdentifier(ColumnIdentifier.newBuilder().setColumnName(columnName)); } - public static org.hypertrace.gateway.service.v1.common.Value convertToGatewayValue( - String attributeName, Value value, Map attributeMetadataMap) { - AttributeMetadata attributeMetadata = attributeMetadataMap.get(attributeName); - if (null == attributeMetadata) { - LOG.warn("No attribute metadata found for {}", attributeName); - return convertQueryValueToGatewayValue(value); - } - return convertQueryValueToGatewayValue(value, attributeMetadata); - } - public static org.hypertrace.gateway.service.v1.common.Value convertQueryValueToGatewayValue( Value value) { org.hypertrace.gateway.service.v1.common.Value.Builder builder = diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/converters/QueryAndGatewayDtoConverter.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/converters/QueryAndGatewayDtoConverter.java index a65f61d6..668eed10 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/converters/QueryAndGatewayDtoConverter.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/converters/QueryAndGatewayDtoConverter.java @@ -4,11 +4,13 @@ import java.time.Duration; import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.function.Predicate; import java.util.stream.Collectors; import org.hypertrace.core.attribute.service.v1.AttributeKind; import org.hypertrace.core.attribute.service.v1.AttributeMetadata; import org.hypertrace.core.attribute.service.v1.AttributeType; -import org.hypertrace.core.query.service.api.ColumnIdentifier; +import org.hypertrace.core.query.service.api.AttributeExpression; import org.hypertrace.core.query.service.api.ColumnMetadata; import org.hypertrace.core.query.service.api.Expression; import org.hypertrace.core.query.service.api.Filter; @@ -19,6 +21,7 @@ import org.hypertrace.core.query.service.api.SortOrder; import org.hypertrace.core.query.service.api.Value; import org.hypertrace.core.query.service.api.ValueType; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -284,37 +287,57 @@ public static Operator convertOperator( throw new IllegalArgumentException("Unsupported operator " + operator.name()); } - private static ColumnIdentifier.Builder convertToQueryColumnIdentifier( + private static AttributeExpression convertToQueryAttributeExpression( + org.hypertrace.gateway.service.v1.common.AttributeExpression attributeExpression) { + AttributeExpression.Builder builder = + AttributeExpression.newBuilder().setAttributeId(attributeExpression.getAttributeId()); + + if (attributeExpression.hasAlias()) { + builder.setAlias(attributeExpression.getAlias()); + } + if (attributeExpression.hasSubpath()) { + builder.setSubpath(attributeExpression.getSubpath()); + } + return builder.build(); + } + + private static AttributeExpression convertToQueryAttributeExpression( org.hypertrace.gateway.service.v1.common.ColumnIdentifier columnIdentifier) { - return ColumnIdentifier.newBuilder() - .setColumnName(columnIdentifier.getColumnName()) - .setAlias(columnIdentifier.getAlias()); + AttributeExpression.Builder builder = + AttributeExpression.newBuilder().setAttributeId(columnIdentifier.getColumnName()); + + Optional.of(columnIdentifier.getAlias()) + .filter(Predicate.not(String::isEmpty)) + .ifPresent(builder::setAlias); + return builder.build(); } public static Expression.Builder convertToQueryExpression( org.hypertrace.gateway.service.v1.common.Expression expression) { - Expression.Builder builder = Expression.newBuilder(); switch (expression.getValueCase()) { case VALUE_NOT_SET: - break; + return Expression.newBuilder(); case COLUMNIDENTIFIER: - builder.setColumnIdentifier( - convertToQueryColumnIdentifier(expression.getColumnIdentifier())); - break; + return Expression.newBuilder() + .setAttributeExpression( + convertToQueryAttributeExpression(expression.getColumnIdentifier())); + case ATTRIBUTE_EXPRESSION: + return Expression.newBuilder() + .setAttributeExpression( + convertToQueryAttributeExpression(expression.getAttributeExpression())); case FUNCTION: - builder.setFunction(convertToQueryFunction(expression.getFunction())); - break; + return Expression.newBuilder() + .setFunction(convertToQueryFunction(expression.getFunction())); case LITERAL: - builder.setLiteral(convertToQueryLiteral(expression.getLiteral())); - break; + return Expression.newBuilder().setLiteral(convertToQueryLiteral(expression.getLiteral())); case ORDERBY: - builder.setOrderBy(convertToQueryOrderBy(expression.getOrderBy())); - break; + return Expression.newBuilder().setOrderBy(convertToQueryOrderBy(expression.getOrderBy())); case HEALTH: - throw new IllegalArgumentException("Cannot convert HEALTH expression to query expression."); + default: + throw new IllegalArgumentException( + String.format( + "Cannot convert %s expression to query expression.", expression.getValueCase())); } - - return builder; } private static OrderByExpression convertToQueryOrderBy( @@ -384,7 +407,7 @@ private static Function convertToQueryFunction( // percentile. List columns = function.getArgumentsList().stream() - .filter(org.hypertrace.gateway.service.v1.common.Expression::hasColumnIdentifier) + .filter(ExpressionReader::isAttributeSelection) .collect(Collectors.toList()); columns.forEach(e -> builder.addArguments(convertToQueryExpression(e))); break; @@ -471,8 +494,20 @@ private static boolean hasTimeRangeFilter(Filter filter, String timestampAttribu return filter.getChildFilterList().stream() .anyMatch(f -> hasTimeRangeFilter(f, timestampAttributeId)); } - return filter.getLhs().getValueCase() == Expression.ValueCase.COLUMNIDENTIFIER - && filter.getLhs().getColumnIdentifier().getColumnName().equals(timestampAttributeId); + return getAttributeIdFromAttributeSelection(filter.getLhs()) + .map(filterAttributeId -> filterAttributeId.equals(timestampAttributeId)) + .orElse(false); + } + + private static Optional getAttributeIdFromAttributeSelection(Expression expression) { + switch (expression.getValueCase()) { + case COLUMNIDENTIFIER: + return Optional.of(expression.getColumnIdentifier().getColumnName()); + case ATTRIBUTE_EXPRESSION: + return Optional.of(expression.getAttributeExpression().getAttributeId()); + default: + return Optional.empty(); + } } private static boolean isNonDefaultFilter( @@ -500,26 +535,25 @@ public static List convertToQueryOrderByExpressions( */ public static org.hypertrace.gateway.service.v1.common.Value convertToGatewayValueForMetricValue( Map aliasToOverrideKind, - Map attributeMetadataMap, + Map resultKeyToAttributeMetadataMap, ColumnMetadata metadata, Value queryValue) { AttributeKind overrideKind = aliasToOverrideKind.get(metadata.getColumnName()); return convertToGatewayValueForMetricValue( - overrideKind, attributeMetadataMap, metadata, queryValue); + overrideKind, resultKeyToAttributeMetadataMap, metadata, queryValue); } public static org.hypertrace.gateway.service.v1.common.Value convertToGatewayValueForMetricValue( AttributeKind attributeKind, - Map attributeMetadataMap, + Map resultKeyToAttributeMetadataMap, ColumnMetadata metadata, Value queryValue) { - String columnName = metadata.getColumnName(); - org.hypertrace.gateway.service.v1.common.Value gwValue; + String resultKey = metadata.getColumnName(); // if there's no override from the function, then this is regular attribute, then // use the attribute map to convert the value AttributeMetadata attributeMetadata; if (attributeKind == null) { - attributeMetadata = attributeMetadataMap.get(columnName); + attributeMetadata = resultKeyToAttributeMetadataMap.get(resultKey); } else { attributeMetadata = AttributeMetadata.newBuilder() @@ -530,12 +564,10 @@ public static org.hypertrace.gateway.service.v1.common.Value convertToGatewayVal } LOG.debug( "Converting {} from type: {} to type: {}", - columnName, + resultKey, metadata.getValueType().name(), attributeMetadata.getValueKind().name()); - gwValue = - QueryAndGatewayDtoConverter.convertQueryValueToGatewayValue(queryValue, attributeMetadata); - - return gwValue; + return QueryAndGatewayDtoConverter.convertQueryValueToGatewayValue( + queryValue, attributeMetadata); } } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/converters/QueryRequestUtil.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/converters/QueryRequestUtil.java index 1cfd6d1d..42541fa4 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/converters/QueryRequestUtil.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/converters/QueryRequestUtil.java @@ -1,7 +1,7 @@ package org.hypertrace.gateway.service.common.converters; import java.util.List; -import org.hypertrace.core.query.service.api.ColumnIdentifier; +import org.hypertrace.core.query.service.api.AttributeExpression; import org.hypertrace.core.query.service.api.Expression; import org.hypertrace.core.query.service.api.Filter; import org.hypertrace.core.query.service.api.Function; @@ -29,16 +29,16 @@ public static Filter createBetweenTimesFilter(String columnName, long lower, lon .build(); } - public static Expression createColumnExpression(String columnName) { + public static Expression createAttributeExpression(String attributeId) { return Expression.newBuilder() - .setColumnIdentifier(ColumnIdentifier.newBuilder().setColumnName(columnName)) + .setAttributeExpression(AttributeExpression.newBuilder().setAttributeId(attributeId)) .build(); } - public static Expression createColumnExpression(String columnName, String alias) { + public static Expression createAttributeExpression(String attributeId, String alias) { return Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder().setColumnName(columnName).setAlias(alias)) + .setAttributeExpression( + AttributeExpression.newBuilder().setAttributeId(attributeId).setAlias(alias)) .build(); } @@ -51,7 +51,7 @@ public static Filter createLongFilter(String columnName, Operator op, long value } public static Filter createFilter(String columnName, Operator op, Expression value) { - return createFilter(createColumnExpression(columnName), op, value); + return createFilter(createAttributeExpression(columnName), op, value); } public static Filter createFilter(Expression columnExpression, Operator op, Expression value) { @@ -97,30 +97,31 @@ public static Expression createStringArrayLiteralExpression(List strings .build(); } - public static Expression createCountByColumnSelection(String columnName) { + public static Expression createCountByColumnSelection(String attributeId) { return Expression.newBuilder() .setFunction( Function.newBuilder() .setFunctionName(COUNT_FUNCTION_NAME) - .addArguments(createColumnExpression(columnName))) + .addArguments(createAttributeExpression(attributeId))) .build(); } - public static Expression createDistinctCountByColumnSelection(String columnName) { + public static Expression createDistinctCountByColumnSelection(String attributeId) { return Expression.newBuilder() .setFunction( Function.newBuilder() .setFunctionName(DISTINCTCOUNT_FUNCTION_NAME) - .addArguments(createColumnExpression(columnName))) + .addArguments(createAttributeExpression(attributeId))) .build(); } - public static Expression createTimeColumnGroupByExpression(String timeColumn, long periodSecs) { + public static Expression createTimeColumnGroupByExpression( + String timeAttributeId, long periodSecs) { return Expression.newBuilder() .setFunction( Function.newBuilder() .setFunctionName(DATE_TIME_CONVERTER) - .addArguments(createColumnExpression(timeColumn)) + .addArguments(createAttributeExpression(timeAttributeId)) .addArguments(createStringLiteralExpression("1:MILLISECONDS:EPOCH")) .addArguments(createStringLiteralExpression("1:MILLISECONDS:EPOCH")) .addArguments(createStringLiteralExpression(periodSecs + ":SECONDS"))) diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/datafetcher/EntityDataServiceEntityFetcher.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/datafetcher/EntityDataServiceEntityFetcher.java index 734d4ffd..3c30ba7e 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/datafetcher/EntityDataServiceEntityFetcher.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/datafetcher/EntityDataServiceEntityFetcher.java @@ -1,13 +1,16 @@ package org.hypertrace.gateway.service.common.datafetcher; +import static org.hypertrace.gateway.service.common.util.ExpressionReader.getExpectedResultNamesForEachAttributeId; + import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.stream.Collectors; import java.util.stream.IntStream; +import org.hypertrace.core.attribute.service.v1.AttributeMetadata; import org.hypertrace.entity.query.service.client.EntityQueryServiceClient; -import org.hypertrace.entity.query.service.v1.ColumnMetadata; import org.hypertrace.entity.query.service.v1.EntityQueryRequest; import org.hypertrace.entity.query.service.v1.ResultSetChunk; import org.hypertrace.entity.query.service.v1.Row; @@ -16,10 +19,10 @@ import org.hypertrace.gateway.service.common.AttributeMetadataProvider; import org.hypertrace.gateway.service.common.converters.EntityServiceAndGatewayServiceConverter; import org.hypertrace.gateway.service.common.util.AttributeMetadataUtil; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.entity.EntitiesRequestContext; import org.hypertrace.gateway.service.entity.EntityKey; import org.hypertrace.gateway.service.entity.config.EntityIdColumnsConfigs; -import org.hypertrace.gateway.service.v1.common.Expression.ValueCase; import org.hypertrace.gateway.service.v1.common.Value; import org.hypertrace.gateway.service.v1.common.ValueType; import org.hypertrace.gateway.service.v1.entity.EntitiesRequest; @@ -50,12 +53,15 @@ public EntityDataServiceEntityFetcher( @Override public EntityFetcherResponse getEntities( EntitiesRequestContext requestContext, EntitiesRequest entitiesRequest) { - List mappedEntityIdAttributeIds = + List entityIdAttributeIds = AttributeMetadataUtil.getIdAttributeIds( attributeMetadataProvider, entityIdColumnsConfigs, requestContext, entitiesRequest.getEntityType()); + Map> requestedAliasesByEntityIdAttributeIds = + getExpectedResultNamesForEachAttributeId( + entitiesRequest.getSelectionList(), entityIdAttributeIds); EntityQueryRequest.Builder builder = EntityQueryRequest.newBuilder() .setEntityType(entitiesRequest.getEntityType()) @@ -64,7 +70,7 @@ public EntityFetcherResponse getEntities( entitiesRequest.getFilter())) // Add EntityID attributes as the first selection .addAllSelection( - mappedEntityIdAttributeIds.stream() + entityIdAttributeIds.stream() .map( entityIdAttr -> EntityServiceAndGatewayServiceConverter.createColumnExpression( @@ -85,11 +91,12 @@ public EntityFetcherResponse getEntities( // Add all expressions in the select that are already not part of the EntityID attributes entitiesRequest.getSelectionList().stream() - .filter(expression -> expression.getValueCase() == ValueCase.COLUMNIDENTIFIER) + .filter(ExpressionReader::isAttributeSelection) .filter( expression -> - !mappedEntityIdAttributeIds.contains( - expression.getColumnIdentifier().getColumnName())) + ExpressionReader.getAttributeIdFromAttributeSelection(expression) + .map(attributeId -> !entityIdAttributeIds.contains(attributeId)) + .orElse(true)) .forEach( expression -> builder.addSelection( @@ -113,21 +120,18 @@ public EntityFetcherResponse getEntities( } EntityQueryRequest entityQueryRequest = builder.build(); - if (LOG.isDebugEnabled()) { - LOG.debug("Sending Query to EDS ======== \n {}", entityQueryRequest); - } - + LOG.debug("Sending Query to EDS ======== \n {}", entityQueryRequest); Iterator resultSetChunkIterator = entityQueryServiceClient.execute(builder.build(), requestContext.getHeaders()); + Map resultMetadataMap = + this.getAttributeMetadataByAlias(requestContext, entitiesRequest); // We want to retain the order as returned from the respective source. Hence using a // LinkedHashMap Map entityBuilders = new LinkedHashMap<>(); while (resultSetChunkIterator.hasNext()) { ResultSetChunk chunk = resultSetChunkIterator.next(); - if (LOG.isDebugEnabled()) { - LOG.debug("Received chunk: " + chunk.toString()); - } + LOG.debug("Received chunk: {}", chunk); if (chunk.getRowCount() < 1) { break; @@ -137,7 +141,7 @@ public EntityFetcherResponse getEntities( // Construct the entity id from the entityIdAttributes columns EntityKey entityKey = EntityKey.of( - IntStream.range(0, mappedEntityIdAttributeIds.size()) + IntStream.range(0, entityIdAttributeIds.size()) .mapToObj(value -> row.getColumn(value).getString()) .toArray(String[]::new)); Builder entityBuilder = entityBuilders.computeIfAbsent(entityKey, k -> Entity.newBuilder()); @@ -147,28 +151,31 @@ public EntityFetcherResponse getEntities( // Always include the id in entity since that's needed to make follow up queries in // optimal fashion. If this wasn't really requested by the client, it should be removed // as post processing. - for (int i = 0; i < mappedEntityIdAttributeIds.size(); i++) { + for (int i = 0; i < entityIdAttributeIds.size(); i++) { entityBuilder.putAttribute( - mappedEntityIdAttributeIds.get(i), + entityIdAttributeIds.get(i), Value.newBuilder() .setString(entityKey.getAttributes().get(i)) .setValueType(ValueType.STRING) .build()); } - for (int i = mappedEntityIdAttributeIds.size(); + requestedAliasesByEntityIdAttributeIds.forEach( + (attributeId, requestedAliasList) -> + requestedAliasList.forEach( + requestedAlias -> + entityBuilder.putAttribute( + requestedAlias, entityBuilder.getAttributeOrThrow(attributeId)))); + + for (int i = entityIdAttributeIds.size(); i < chunk.getResultSetMetadata().getColumnMetadataCount(); i++) { - ColumnMetadata metadata = chunk.getResultSetMetadata().getColumnMetadata(i); - - String attributeName = metadata.getColumnName(); + String resultName = chunk.getResultSetMetadata().getColumnMetadata(i).getColumnName(); + AttributeMetadata attributeMetadata = resultMetadataMap.get(resultName); entityBuilder.putAttribute( - attributeName, - EntityServiceAndGatewayServiceConverter.convertToGatewayValue( - attributeName, - row.getColumn(i), - attributeMetadataProvider.getAttributesMetadata( - requestContext, entitiesRequest.getEntityType()))); + resultName, + EntityServiceAndGatewayServiceConverter.convertQueryValueToGatewayValue( + row.getColumn(i), attributeMetadata)); } } } @@ -212,4 +219,24 @@ public long getTotal(EntitiesRequestContext requestContext, EntitiesRequest enti entityQueryServiceClient.total(totalEntitiesRequest, requestContext.getHeaders()); return response.getTotal(); } + + private Map getAttributeMetadataByAlias( + EntitiesRequestContext requestContext, EntitiesRequest request) { + Map attributeMetadataByIdMap = + attributeMetadataProvider.getAttributesMetadata(requestContext, request.getEntityType()); + return request.getSelectionList().stream() + .filter( + expression -> + ExpressionReader.getAttributeIdFromAttributeSelection(expression) + .map(attributeMetadataByIdMap::containsKey) + .orElse(false)) + .map( + expression -> + Map.entry( + ExpressionReader.getSelectionResultName(expression).orElseThrow(), + attributeMetadataByIdMap.get( + ExpressionReader.getAttributeIdFromAttributeSelection(expression) + .orElseThrow()))) + .collect(Collectors.toUnmodifiableMap(Entry::getKey, Entry::getValue, (x, y) -> x)); + } } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/datafetcher/EntityInteractionsFetcher.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/datafetcher/EntityInteractionsFetcher.java index 773f4614..6c88b7d2 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/datafetcher/EntityInteractionsFetcher.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/datafetcher/EntityInteractionsFetcher.java @@ -36,6 +36,7 @@ import org.hypertrace.gateway.service.common.converters.QueryAndGatewayDtoConverter; import org.hypertrace.gateway.service.common.converters.QueryRequestUtil; import org.hypertrace.gateway.service.common.util.AttributeMetadataUtil; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.common.util.MetricAggregationFunctionUtil; import org.hypertrace.gateway.service.entity.EntityKey; import org.hypertrace.gateway.service.entity.config.InteractionConfig; @@ -171,13 +172,6 @@ private void addInteractions( throw new IllegalArgumentException(errorMsg); } - Set selectedColumns = new HashSet<>(); - for (Expression expression : interactionsRequest.getSelectionList()) { - if (expression.getValueCase() == ValueCase.COLUMNIDENTIFIER) { - selectedColumns.add(expression.getColumnIdentifier().getColumnName()); - } - } - Map metricToAggFunction = MetricAggregationFunctionUtil.getAggMetricToFunction( interactionsRequest.getSelectionList()); @@ -188,7 +182,7 @@ private void addInteractions( parseResultSet( request.getEntityType(), entry.getKey(), - selectedColumns, + interactionsRequest.getSelectionList(), metricToAggFunction, resultSet, incoming, @@ -205,14 +199,13 @@ private Set getOtherEntityTypes(org.hypertrace.gateway.service.v1.common return result; } } - } else { - if (filter.getLhs().getValueCase() == ValueCase.COLUMNIDENTIFIER) { - String columnName = filter.getLhs().getColumnIdentifier().getColumnName(); + } else if (ExpressionReader.isSimpleAttributeSelection(filter.getLhs())) { + String attributeId = + ExpressionReader.getAttributeIdFromAttributeSelection(filter.getLhs()).orElseThrow(); - if (StringUtils.equals(columnName, FROM_ENTITY_TYPE_ATTRIBUTE_ID) - || StringUtils.equals(columnName, TO_ENTITY_TYPE_ATTRIBUTE_ID)) { - return getValues(filter.getRhs()); - } + if (StringUtils.equals(attributeId, FROM_ENTITY_TYPE_ATTRIBUTE_ID) + || StringUtils.equals(attributeId, TO_ENTITY_TYPE_ATTRIBUTE_ID)) { + return getValues(filter.getRhs()); } } @@ -228,10 +221,11 @@ private Filter convertToQueryFilter( builder.addChildFilter(convertToQueryFilter(child, otherEntityType)); } } else { - if (filter.getLhs().getValueCase() == ValueCase.COLUMNIDENTIFIER) { - String columnName = filter.getLhs().getColumnIdentifier().getColumnName(); + if (ExpressionReader.isSimpleAttributeSelection(filter.getLhs())) { + String attributeId = + ExpressionReader.getAttributeIdFromAttributeSelection(filter.getLhs()).orElseThrow(); - switch (columnName) { + switch (attributeId) { case FROM_ENTITY_TYPE_ATTRIBUTE_ID: return QueryRequestUtil.createCompositeFilter( Operator.AND, @@ -368,15 +362,16 @@ Map buildQueryRequests( // Group by the entity id column first, then the other end entity type for the interaction. List idExpressions = idColumns.stream() - .map(QueryRequestUtil::createColumnExpression) + .map(QueryRequestUtil::createAttributeExpression) .collect(Collectors.toList()); builder.addAllGroupBy(idExpressions); List selections = new ArrayList<>(); for (Expression expression : interactionsRequest.getSelectionList()) { // Ignore the predefined selections because they're handled specially. - if (expression.getValueCase() == ValueCase.COLUMNIDENTIFIER - && SELECTIONS_TO_IGNORE.contains(expression.getColumnIdentifier().getColumnName())) { + if (ExpressionReader.isSimpleAttributeSelection(expression) + && SELECTIONS_TO_IGNORE.contains( + ExpressionReader.getAttributeIdFromAttributeSelection(expression).orElseThrow())) { continue; } @@ -414,7 +409,7 @@ Map buildQueryRequests( getEntityIdColumnsFromInteraction(otherEntityType, incoming); List otherIdExpressions = otherEntityIdColumns.stream() - .map(QueryRequestUtil::createColumnExpression) + .map(QueryRequestUtil::createAttributeExpression) .collect(Collectors.toList()); builderCopy.addAllGroupBy(otherIdExpressions); @@ -440,7 +435,7 @@ Map buildQueryRequests( private void parseResultSet( String entityType, String otherEntityType, - Set selectedColumns, + Collection selections, Map metricToAggFunction, Iterator resultset, boolean incoming, @@ -451,7 +446,7 @@ private void parseResultSet( metadataProvider.getAttributesMetadata(requestContext, SCOPE); Map aliasToAttributeKind = - MetricAggregationFunctionUtil.getValueTypeFromFunction( + MetricAggregationFunctionUtil.getValueTypeForFunctionType( metricToAggFunction, attributeMetadataMap); while (resultset.hasNext()) { @@ -489,7 +484,7 @@ private void parseResultSet( addInteractionEdges( interaction, - selectedColumns, + selections, incoming ? otherEntityType : entityType, incoming ? otherEntityId : entityId, incoming ? entityType : otherEntityType, @@ -539,37 +534,48 @@ private void parseResultSet( private void addInteractionEdges( EntityInteraction.Builder interaction, - Set selectedColumns, + Collection selections, String fromEntityType, EntityKey fromEntityId, String toEntityType, EntityKey toEntityId) { - if (selectedColumns.contains(FROM_ENTITY_ID_ATTRIBUTE_ID)) { + Map selectionResultNames = + selections.stream() + .filter(ExpressionReader::isSimpleAttributeSelection) + .collect( + Collectors.toUnmodifiableMap( + expression -> + ExpressionReader.getAttributeIdFromAttributeSelection(expression) + .orElseThrow(), + expression -> + ExpressionReader.getSelectionResultName(expression).orElseThrow())); + + if (selectionResultNames.containsKey(FROM_ENTITY_ID_ATTRIBUTE_ID)) { interaction.putAttribute( - FROM_ENTITY_ID_ATTRIBUTE_ID, + selectionResultNames.get(FROM_ENTITY_ID_ATTRIBUTE_ID), Value.newBuilder() .setString(fromEntityId.toString()) .setValueType(ValueType.STRING) .build()); } - if (selectedColumns.contains(FROM_ENTITY_TYPE_ATTRIBUTE_ID)) { + if (selectionResultNames.containsKey(FROM_ENTITY_TYPE_ATTRIBUTE_ID)) { interaction.putAttribute( - FROM_ENTITY_TYPE_ATTRIBUTE_ID, + selectionResultNames.get(FROM_ENTITY_TYPE_ATTRIBUTE_ID), Value.newBuilder().setString(fromEntityType).setValueType(ValueType.STRING).build()); } - if (selectedColumns.contains(TO_ENTITY_ID_ATTRIBUTE_ID)) { + if (selectionResultNames.containsKey(TO_ENTITY_ID_ATTRIBUTE_ID)) { interaction.putAttribute( - TO_ENTITY_ID_ATTRIBUTE_ID, + selectionResultNames.get(TO_ENTITY_ID_ATTRIBUTE_ID), Value.newBuilder() .setString(toEntityId.toString()) .setValueType(ValueType.STRING) .build()); } - if (selectedColumns.contains(TO_ENTITY_TYPE_ATTRIBUTE_ID)) { + if (selectionResultNames.containsKey(TO_ENTITY_TYPE_ATTRIBUTE_ID)) { interaction.putAttribute( - TO_ENTITY_TYPE_ATTRIBUTE_ID, + selectionResultNames.get(TO_ENTITY_TYPE_ATTRIBUTE_ID), Value.newBuilder().setString(toEntityType).setValueType(ValueType.STRING).build()); } } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/datafetcher/QueryServiceEntityFetcher.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/datafetcher/QueryServiceEntityFetcher.java index 3b10ed94..ce0c1ed3 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/datafetcher/QueryServiceEntityFetcher.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/datafetcher/QueryServiceEntityFetcher.java @@ -1,13 +1,16 @@ package org.hypertrace.gateway.service.common.datafetcher; +import static java.util.Objects.isNull; import static org.hypertrace.gateway.service.common.converters.QueryAndGatewayDtoConverter.convertToQueryExpression; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createCountByColumnSelection; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createDistinctCountByColumnSelection; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createFilter; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createStringNullLiteralExpression; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createTimeColumnGroupByExpression; +import static org.hypertrace.gateway.service.common.util.ExpressionReader.getExpectedResultNamesForEachAttributeId; import com.google.common.base.Preconditions; +import com.google.common.collect.Streams; import java.time.Duration; import java.time.temporal.ChronoUnit; import java.util.Collection; @@ -42,8 +45,8 @@ import org.hypertrace.gateway.service.entity.EntityKey; import org.hypertrace.gateway.service.entity.config.EntityIdColumnsConfigs; import org.hypertrace.gateway.service.v1.common.AggregatedMetricValue; -import org.hypertrace.gateway.service.v1.common.Expression.ValueCase; import org.hypertrace.gateway.service.v1.common.FunctionExpression; +import org.hypertrace.gateway.service.v1.common.FunctionType; import org.hypertrace.gateway.service.v1.common.Health; import org.hypertrace.gateway.service.v1.common.Interval; import org.hypertrace.gateway.service.v1.common.MetricSeries; @@ -86,20 +89,26 @@ public EntityFetcherResponse getEntities( Map attributeMetadataMap = attributeMetadataProvider.getAttributesMetadata( requestContext, entitiesRequest.getEntityType()); + Map resultKeyToAttributeMetadataMap = + this.remapAttributeMetadataByResultName(entitiesRequest, attributeMetadataMap); // Validate EntitiesRequest entitiesRequestValidator.validate(entitiesRequest, attributeMetadataMap); - List entityIdAttributes = + List entityIdAttributeIds = AttributeMetadataUtil.getIdAttributeIds( attributeMetadataProvider, entityIdColumnsConfigs, requestContext, entitiesRequest.getEntityType()); List aggregates = - ExpressionReader.getFunctionExpressions(entitiesRequest.getSelectionList().stream()); + ExpressionReader.getFunctionExpressions(entitiesRequest.getSelectionList()); + + Map> requestedAliasesByEntityIdAttributeIds = + getExpectedResultNamesForEachAttributeId( + entitiesRequest.getSelectionList(), entityIdAttributeIds); QueryRequest.Builder builder = - constructSelectionQuery(requestContext, entitiesRequest, entityIdAttributes, aggregates); + constructSelectionQuery(requestContext, entitiesRequest, entityIdAttributeIds, aggregates); adjustLimitAndOffset(builder, entitiesRequest.getLimit(), entitiesRequest.getOffset()); @@ -112,9 +121,7 @@ public EntityFetcherResponse getEntities( QueryRequest queryRequest = builder.build(); - if (LOG.isDebugEnabled()) { - LOG.debug("Sending Query to Query Service ======== \n {}", queryRequest); - } + LOG.debug("Sending Query to Query Service ======== \n {}", queryRequest); Iterator resultSetChunkIterator = queryServiceClient.executeQuery(queryRequest, requestContext.getHeaders(), requestTimeout); @@ -124,19 +131,17 @@ public EntityFetcherResponse getEntities( Map entityBuilders = new LinkedHashMap<>(); while (resultSetChunkIterator.hasNext()) { ResultSetChunk chunk = resultSetChunkIterator.next(); - if (LOG.isDebugEnabled()) { - LOG.debug("Received chunk: " + chunk.toString()); - } + LOG.debug("Received chunk: {}", chunk); if (chunk.getRowCount() < 1) { break; } for (Row row : chunk.getRowList()) { - // Construct the entity id from the entityIdAttributes columns + // Construct the entity id from the entityIdAttributeIds columns EntityKey entityKey = EntityKey.of( - IntStream.range(0, entityIdAttributes.size()) + IntStream.range(0, entityIdAttributeIds.size()) .mapToObj(value -> row.getColumn(value).getString()) .toArray(String[]::new)); Builder entityBuilder = entityBuilders.computeIfAbsent(entityKey, k -> Entity.newBuilder()); @@ -145,16 +150,23 @@ public EntityFetcherResponse getEntities( // Always include the id in entity since that's needed to make follow up queries in // optimal fashion. If this wasn't really requested by the client, it should be removed // as post processing. - for (int i = 0; i < entityIdAttributes.size(); i++) { + for (int i = 0; i < entityIdAttributeIds.size(); i++) { entityBuilder.putAttribute( - entityIdAttributes.get(i), + entityIdAttributeIds.get(i), Value.newBuilder() .setString(entityKey.getAttributes().get(i)) .setValueType(ValueType.STRING) .build()); } - for (int i = entityIdAttributes.size(); + requestedAliasesByEntityIdAttributeIds.forEach( + (attributeId, requestedAliasList) -> + requestedAliasList.forEach( + requestedAlias -> + entityBuilder.putAttribute( + requestedAlias, entityBuilder.getAttributeOrThrow(attributeId)))); + + for (int i = entityIdAttributeIds.size(); i < chunk.getResultSetMetadata().getColumnMetadataCount(); i++) { ColumnMetadata metadata = chunk.getResultSetMetadata().getColumnMetadata(i); @@ -162,15 +174,13 @@ public EntityFetcherResponse getEntities( buildEntity( entityBuilder, requestContext, - entitiesRequest, metadata, columnValue, - attributeMetadataMap, + resultKeyToAttributeMetadataMap, aggregates.isEmpty()); } } } - return new EntityFetcherResponse(entityBuilders); } @@ -201,14 +211,14 @@ private void adjustLimitAndOffset(QueryRequest.Builder builder, int limit, int o private QueryRequest.Builder constructSelectionQuery( EntitiesRequestContext requestContext, EntitiesRequest entitiesRequest, - List entityIdAttributes, + List entityIdAttributeIds, List aggregates) { List idExpressions = - entityIdAttributes.stream() - .map(QueryRequestUtil::createColumnExpression) + entityIdAttributeIds.stream() + .map(QueryRequestUtil::createAttributeExpression) .collect(Collectors.toList()); Filter.Builder filterBuilder = - constructQueryServiceFilter(entitiesRequest, requestContext, entityIdAttributes); + constructQueryServiceFilter(entitiesRequest, requestContext, entityIdAttributeIds); QueryRequest.Builder builder = QueryRequest.newBuilder() @@ -230,10 +240,12 @@ private QueryRequest.Builder constructSelectionQuery( // TODO: Query non identifying attributes from entity service in parallel to this query // and remove this logic. entitiesRequest.getSelectionList().stream() - .filter(expression -> expression.getValueCase() == ValueCase.COLUMNIDENTIFIER) + .filter(ExpressionReader::isAttributeSelection) .filter( expression -> - !entityIdAttributes.contains(expression.getColumnIdentifier().getColumnName())) + ExpressionReader.getAttributeIdFromAttributeSelection(expression) + .map(attributeId -> !entityIdAttributeIds.contains(attributeId)) + .orElse(true)) .forEach( expression -> { Expression.Builder expBuilder = convertToQueryExpression(expression); @@ -246,7 +258,7 @@ private QueryRequest.Builder constructSelectionQuery( if (aggregates.isEmpty()) { builder.addSelection( createCountByColumnSelection( - Optional.ofNullable(entityIdAttributes.get(0)).orElseThrow())); + Optional.ofNullable(entityIdAttributeIds.get(0)).orElseThrow())); } return builder; } @@ -254,10 +266,9 @@ private QueryRequest.Builder constructSelectionQuery( private void buildEntity( Entity.Builder entityBuilder, QueryRequestContext requestContext, - EntitiesRequest entitiesRequest, ColumnMetadata metadata, org.hypertrace.core.query.service.api.Value columnValue, - Map attributeMetadataMap, + Map resultKeyToAttributeMetadataMap, boolean isSkipCountColumn) { // Ignore the count column since we introduced that ourselves into the query @@ -269,15 +280,10 @@ private void buildEntity( // aggregate if (requestContext.containsFunctionExpression(metadata.getColumnName())) { addAggregateMetric( - entityBuilder, - requestContext, - entitiesRequest, - metadata, - columnValue, - attributeMetadataMap); + entityBuilder, requestContext, metadata, columnValue, resultKeyToAttributeMetadataMap); } else { // attribute - addEntityAttribute(entityBuilder, metadata, columnValue, attributeMetadataMap); + addEntityAttribute(entityBuilder, metadata, columnValue, resultKeyToAttributeMetadataMap); } } @@ -285,27 +291,36 @@ private void addEntityAttribute( Entity.Builder entityBuilder, ColumnMetadata metadata, org.hypertrace.core.query.service.api.Value columnValue, - Map attributeMetadataMap) { + Map resultKeyToAttributeMetadataMap) { + + String resultKey = metadata.getColumnName(); + if (!resultKeyToAttributeMetadataMap.containsKey(resultKey)) { + LOG.warn("Missing attribute metadata for key {}", resultKey); + } - String attributeName = metadata.getColumnName(); entityBuilder.putAttribute( - attributeName, - QueryAndGatewayDtoConverter.convertToGatewayValue( - attributeName, columnValue, attributeMetadataMap)); + resultKey, + QueryAndGatewayDtoConverter.convertQueryValueToGatewayValue( + columnValue, resultKeyToAttributeMetadataMap.get(resultKey))); } private void addAggregateMetric( Entity.Builder entityBuilder, QueryRequestContext requestContext, - EntitiesRequest entitiesRequest, ColumnMetadata metadata, org.hypertrace.core.query.service.api.Value columnValue, - Map attributeMetadataMap) { + Map resultKeyToAttributeMetadataMap) { - FunctionExpression function = + FunctionExpression functionExpression = requestContext.getFunctionExpressionByAlias(metadata.getColumnName()); + AttributeMetadata functionAttributeMetadata = + resultKeyToAttributeMetadataMap.get(metadata.getColumnName()); + + if (isNull(functionAttributeMetadata)) { + LOG.warn("Missing attribute metadata for {}", metadata.getColumnName()); + } List healthExpressions = - function.getArgumentsList().stream() + functionExpression.getArgumentsList().stream() .filter(org.hypertrace.gateway.service.v1.common.Expression::hasHealth) .collect(Collectors.toList()); Preconditions.checkArgument(healthExpressions.size() <= 1); @@ -313,8 +328,9 @@ private void addAggregateMetric( Value convertedValue = QueryAndGatewayDtoConverter.convertToGatewayValueForMetricValue( - MetricAggregationFunctionUtil.getValueTypeFromFunction(function, attributeMetadataMap), - attributeMetadataMap, + MetricAggregationFunctionUtil.getValueTypeForFunctionType( + functionExpression.getFunction(), functionAttributeMetadata), + resultKeyToAttributeMetadataMap, metadata, columnValue); @@ -322,7 +338,7 @@ private void addAggregateMetric( metadata.getColumnName(), AggregatedMetricValue.newBuilder() .setValue(convertedValue) - .setFunction(function.getFunction()) + .setFunction(functionExpression.getFunction()) .setHealth(health) .build()); } @@ -348,6 +364,9 @@ public EntityFetcherResponse getTimeAggregatedMetrics( attributeMetadataProvider.getAttributesMetadata( requestContext, entitiesRequest.getEntityType()); + Map resultKeyToAttributeMetadataMap = + this.remapAttributeMetadataByResultName(entitiesRequest, attributeMetadataMap); + entitiesRequestValidator.validate(entitiesRequest, attributeMetadataMap); entitiesRequest @@ -402,7 +421,7 @@ public EntityFetcherResponse getTimeAggregatedMetrics( } for (Row row : chunk.getRowList()) { - // Construct the entity id from the entityIdAttributes columns + // Construct the entity id from the entityIdAttributeIds columns EntityKey entityKey = EntityKey.of( IntStream.range(0, idColumns.size()) @@ -430,17 +449,21 @@ public EntityFetcherResponse getTimeAggregatedMetrics( ColumnMetadata metadata = chunk.getResultSetMetadata().getColumnMetadata(i); TimeAggregation timeAggregation = requestContext.getTimeAggregationByAlias(metadata.getColumnName()); - if (timeAggregation == null) { LOG.warn("Couldn't find an aggregate for column: {}", metadata.getColumnName()); continue; } + FunctionType functionType = + timeAggregation.getAggregation().getFunction().getFunction(); + AttributeMetadata functionAttributeMetadata = + resultKeyToAttributeMetadataMap.get(metadata.getColumnName()); + Value convertedValue = QueryAndGatewayDtoConverter.convertToGatewayValueForMetricValue( - MetricAggregationFunctionUtil.getValueTypeFromFunction( - timeAggregation.getAggregation().getFunction(), attributeMetadataMap), - attributeMetadataMap, + MetricAggregationFunctionUtil.getValueTypeForFunctionType( + functionType, functionAttributeMetadata), + resultKeyToAttributeMetadataMap, metadata, row.getColumn(i)); @@ -501,7 +524,7 @@ public long getTotal(EntitiesRequestContext requestContext, EntitiesRequest enti // Validate EntitiesRequest entitiesRequestValidator.validate(entitiesRequest, attributeMetadataMap); - List entityIdAttributes = + List entityIdAttributeIds = AttributeMetadataUtil.getIdAttributeIds( attributeMetadataProvider, entityIdColumnsConfigs, @@ -509,13 +532,13 @@ public long getTotal(EntitiesRequestContext requestContext, EntitiesRequest enti entitiesRequest.getEntityType()); Filter.Builder filterBuilder = - constructQueryServiceFilter(entitiesRequest, requestContext, entityIdAttributes); + constructQueryServiceFilter(entitiesRequest, requestContext, entityIdAttributeIds); QueryRequest queryRequest = QueryRequest.newBuilder() .addSelection( createDistinctCountByColumnSelection( - Optional.ofNullable(entityIdAttributes.get(0)).orElseThrow())) + Optional.ofNullable(entityIdAttributeIds.get(0)).orElseThrow())) .setFilter(filterBuilder) .build(); @@ -584,7 +607,7 @@ private QueryRequest buildTimeSeriesQueryRequest( // First group by the id columns. builder.addAllGroupBy( idColumns.stream() - .map(QueryRequestUtil::createColumnExpression) + .map(QueryRequestUtil::createAttributeExpression) .collect(Collectors.toList())); // Secondary grouping is on time. @@ -607,13 +630,13 @@ private QueryRequest buildTimeSeriesQueryRequest( private Filter.Builder constructQueryServiceFilter( EntitiesRequest entitiesRequest, EntitiesRequestContext context, - List entityIdAttributes) { + List entityIdAttributeIds) { // adds the Id != "null" filter to remove null entities. Filter.Builder filterBuilder = Filter.newBuilder() .setOperator(Operator.AND) .addAllChildFilter( - entityIdAttributes.stream() + entityIdAttributeIds.stream() .map( entityIdAttribute -> createFilter( @@ -647,4 +670,14 @@ private MetricSeries.Builder getMetricSeriesBuilder(TimeAggregation timeAggregat series.setPeriod(timeAggregation.getPeriod()); return series; } + + private Map remapAttributeMetadataByResultName( + EntitiesRequest request, Map attributeMetadataByIdMap) { + return AttributeMetadataUtil.remapAttributeMetadataByResultKey( + Streams.concat( + request.getSelectionList().stream(), + request.getTimeAggregationList().stream().map(TimeAggregation::getAggregation)) + .collect(Collectors.toList()), + attributeMetadataByIdMap); + } } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/transformer/RequestPreProcessor.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/transformer/RequestPreProcessor.java index cbf62c67..6b62fa5d 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/transformer/RequestPreProcessor.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/transformer/RequestPreProcessor.java @@ -1,16 +1,11 @@ package org.hypertrace.gateway.service.common.transformer; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.stream.Collectors; import org.hypertrace.gateway.service.common.AttributeMetadataProvider; import org.hypertrace.gateway.service.common.RequestContext; import org.hypertrace.gateway.service.common.config.ScopeFilterConfigs; import org.hypertrace.gateway.service.entity.EntitiesRequestContext; import org.hypertrace.gateway.service.trace.TraceScope; -import org.hypertrace.gateway.service.v1.common.Expression; -import org.hypertrace.gateway.service.v1.common.Expression.ValueCase; import org.hypertrace.gateway.service.v1.common.Filter; import org.hypertrace.gateway.service.v1.entity.EntitiesRequest; import org.hypertrace.gateway.service.v1.trace.TracesRequest; @@ -37,10 +32,10 @@ public RequestPreProcessor( * This is called once before processing the request. * * @param originalRequest The original request received - * @return The modified request with any additional filters depending on the scope config + * @return The modified request with unique selections and any additional filters depending on the + * scope config */ - public EntitiesRequest transformFilter( - EntitiesRequest originalRequest, EntitiesRequestContext context) { + public EntitiesRequest process(EntitiesRequest originalRequest, EntitiesRequestContext context) { EntitiesRequest.Builder entitiesRequestBuilder = EntitiesRequest.newBuilder(originalRequest); // Add any additional filters that maybe defined in the scope filters config Filter filter = @@ -51,10 +46,10 @@ public EntitiesRequest transformFilter( context); return entitiesRequestBuilder - .clearSelection() .setFilter(filter) - // Clean out duplicate columns in selections - .addAllSelection(getUniqueSelections(originalRequest.getSelectionList())) + .clearSelection() + .addAllSelection( + originalRequest.getSelectionList().stream().distinct().collect(Collectors.toList())) .build(); } @@ -64,8 +59,7 @@ public EntitiesRequest transformFilter( * @param originalRequest The original request received * @return The modified request with any additional filters in scope filters config */ - public TracesRequest transformFilter( - TracesRequest originalRequest, RequestContext requestContext) { + public TracesRequest process(TracesRequest originalRequest, RequestContext requestContext) { TracesRequest.Builder tracesRequestBuilder = TracesRequest.newBuilder(originalRequest); // Add any additional filters that maybe defined in the scope filters config @@ -77,24 +71,4 @@ public TracesRequest transformFilter( return tracesRequestBuilder.build(); } - - private List getUniqueSelections(List expressions) { - List selections = new ArrayList<>(); - Set uniqueColumnNames = new HashSet<>(); - - for (Expression expression : expressions) { - // unique columns only - if (expression.getValueCase() == ValueCase.COLUMNIDENTIFIER) { - String columnName = expression.getColumnIdentifier().getColumnName(); - if (!uniqueColumnNames.contains(columnName)) { - uniqueColumnNames.add(columnName); - selections.add(expression); - } - } else { - selections.add(expression); - } - } - - return selections; - } } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/transformer/ResponsePostProcessor.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/transformer/ResponsePostProcessor.java index 5d923c5c..14070676 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/transformer/ResponsePostProcessor.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/transformer/ResponsePostProcessor.java @@ -2,8 +2,10 @@ import java.util.Collection; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.entity.query.ExecutionContext; import org.hypertrace.gateway.service.v1.common.AggregatedMetricValue; import org.hypertrace.gateway.service.v1.common.MetricSeries; @@ -20,7 +22,8 @@ public List transform( Set selections = executionContext.getSourceToSelectionExpressionMap().values().stream() .flatMap(Collection::stream) - .map(expression -> expression.getColumnIdentifier().getAlias()) + .map(ExpressionReader::getSelectionResultName) + .flatMap(Optional::stream) .collect(Collectors.toSet()); Set aggregations = executionContext.getSourceToMetricExpressionMap().values().stream() diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/AttributeMetadataUtil.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/AttributeMetadataUtil.java index 1ebfd9e0..274af50f 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/AttributeMetadataUtil.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/AttributeMetadataUtil.java @@ -1,6 +1,9 @@ package org.hypertrace.gateway.service.common.util; +import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; @@ -11,6 +14,7 @@ import org.hypertrace.gateway.service.common.exp.UnknownScopeAndKeyForAttributeException; import org.hypertrace.gateway.service.entity.config.EntityIdColumnsConfigs; import org.hypertrace.gateway.service.entity.config.TimestampConfigs; +import org.hypertrace.gateway.service.v1.common.Expression; /** Utility class for fetching AttributeMetadata */ public class AttributeMetadataUtil { @@ -111,4 +115,22 @@ private static AttributeMetadata getAttributeMetadata( .getAttributeMetadata(requestContext, scope, key) .orElseThrow(() -> new UnknownScopeAndKeyForAttributeException(scope, key)); } + + public static Map remapAttributeMetadataByResultKey( + Collection selections, Map attributeMetadataByIdMap) { + return selections.stream() + .filter( + expression -> + ExpressionReader.getAttributeIdFromAttributeSelection(expression) + .map(attributeMetadataByIdMap::containsKey) + .orElse(false)) + .map( + expression -> + Map.entry( + ExpressionReader.getSelectionResultName(expression).orElseThrow(), + attributeMetadataByIdMap.get( + ExpressionReader.getAttributeIdFromAttributeSelection(expression) + .orElseThrow()))) + .collect(Collectors.toUnmodifiableMap(Entry::getKey, Entry::getValue, (x, y) -> x)); + } } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/ExpressionReader.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/ExpressionReader.java index bb320a01..ac52af47 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/ExpressionReader.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/ExpressionReader.java @@ -1,47 +1,52 @@ package org.hypertrace.gateway.service.common.util; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -import java.util.stream.Stream; import org.hypertrace.gateway.service.v1.common.Expression; +import org.hypertrace.gateway.service.v1.common.FunctionExpression; public class ExpressionReader { - public static List getFunctionExpressions(Stream expressionStream) { - return expressionStream + public static List getFunctionExpressions(List expressions) { + return expressions.stream() .filter(expression -> expression.getValueCase() == Expression.ValueCase.FUNCTION) - .collect(Collectors.toList()); + .collect(Collectors.toUnmodifiableList()); } - public static List getColumnExpressions(Stream expressionStream) { - return expressionStream - .filter(expression -> expression.getValueCase() == Expression.ValueCase.COLUMNIDENTIFIER) - .collect(Collectors.toList()); + public static List getAttributeExpressions(List expressions) { + return expressions.stream() + .filter(ExpressionReader::isAttributeSelection) + .collect(Collectors.toUnmodifiableList()); } - public static Set extractColumns(Expression expression) { + public static Set extractAttributeIds(Expression expression) { Set columns = new HashSet<>(); - extractColumns(columns, expression); + extractAttributeIds(columns, expression); return Collections.unmodifiableSet(columns); } - private static void extractColumns(Set columns, Expression expression) { + private static void extractAttributeIds(Set columns, Expression expression) { switch (expression.getValueCase()) { case COLUMNIDENTIFIER: String columnName = expression.getColumnIdentifier().getColumnName(); columns.add(columnName); break; + case ATTRIBUTE_EXPRESSION: + columns.add(expression.getAttributeExpression().getAttributeId()); + break; case FUNCTION: for (Expression exp : expression.getFunction().getArgumentsList()) { - extractColumns(columns, exp); + extractAttributeIds(columns, exp); } break; case ORDERBY: - extractColumns(columns, expression.getOrderBy().getExpression()); + extractAttributeIds(columns, expression.getOrderBy().getExpression()); break; case LITERAL: case VALUE_NOT_SET: @@ -49,6 +54,78 @@ private static void extractColumns(Set columns, Expression expression) { } } + public static Optional getAttributeIdFromAttributeSelection(Expression expression) { + switch (expression.getValueCase()) { + case COLUMNIDENTIFIER: + return Optional.of(expression.getColumnIdentifier().getColumnName()); + case ATTRIBUTE_EXPRESSION: + return Optional.of(expression.getAttributeExpression().getAttributeId()); + case FUNCTION: + return getAttributeIdFromAttributeSelection(expression.getFunction()); + default: + return Optional.empty(); + } + } + + public static Optional getAttributeIdFromAttributeSelection( + FunctionExpression functionExpression) { + return functionExpression.getArgumentsList().stream() + .map(ExpressionReader::getAttributeIdFromAttributeSelection) + .flatMap(Optional::stream) + .findFirst(); + } + + public static boolean isSimpleAttributeSelection(Expression expression) { + switch (expression.getValueCase()) { + case ATTRIBUTE_EXPRESSION: + return !expression.getAttributeExpression().hasSubpath(); + case COLUMNIDENTIFIER: + return true; + default: + return false; + } + } + + public static boolean isAttributeSelection(Expression expression) { + switch (expression.getValueCase()) { + case ATTRIBUTE_EXPRESSION: + case COLUMNIDENTIFIER: + return true; + default: + return false; + } + } + + public static Optional getSelectionResultName(Expression expression) { + switch (expression.getValueCase()) { + case COLUMNIDENTIFIER: + return Optional.of( + expression.getColumnIdentifier().getAlias().isEmpty() + ? expression.getColumnIdentifier().getColumnName() + : expression.getColumnIdentifier().getAlias()); + case ATTRIBUTE_EXPRESSION: + return Optional.of( + expression.getAttributeExpression().getAlias().isEmpty() + ? expression.getAttributeExpression().getAttributeId() + : expression.getAttributeExpression().getAlias()); + case FUNCTION: + FunctionExpression functionExpression = expression.getFunction(); + if (!functionExpression.getAlias().isEmpty()) { + return Optional.of(functionExpression.getAlias()); + } + String argumentString = + functionExpression.getArgumentsList().stream() + .map(ExpressionReader::getSelectionResultName) + .flatMap(Optional::stream) + .collect(Collectors.joining(",")); + + return Optional.of( + String.format("%s_%s", functionExpression.getFunction(), argumentString)); + default: + return Optional.empty(); + } + } + /** * Given a source to attributes, builds an attribute to sources map. Basically, a reverse map of * the map provided as input @@ -70,4 +147,21 @@ public static Map> buildAttributeToSourcesMap( } return Collections.unmodifiableMap(attributeToSourcesMap); } + + public static Map> getExpectedResultNamesForEachAttributeId( + Collection expressionList, Collection attributeIds) { + return Map.copyOf( + expressionList.stream() + .filter(ExpressionReader::isSimpleAttributeSelection) + .filter( + attributeSelection -> + attributeIds.contains( + getAttributeIdFromAttributeSelection(attributeSelection).orElseThrow())) + .collect( + Collectors.groupingBy( + expression -> getAttributeIdFromAttributeSelection(expression).orElseThrow(), + Collectors.mapping( + expression -> getSelectionResultName(expression).orElseThrow(), + Collectors.toUnmodifiableList())))); + } } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/MetricAggregationFunctionUtil.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/MetricAggregationFunctionUtil.java index 16d5a577..3c3701be 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/MetricAggregationFunctionUtil.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/MetricAggregationFunctionUtil.java @@ -5,8 +5,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.tuple.ImmutablePair; import org.hypertrace.core.attribute.service.v1.AttributeKind; import org.hypertrace.core.attribute.service.v1.AttributeMetadata; import org.hypertrace.gateway.service.v1.common.Expression; @@ -17,16 +15,6 @@ /** Class with some utility methods around Aggregated metrics, alias in the entity requests. */ public class MetricAggregationFunctionUtil { - private static final String FUNCTION_NAME_SEPARATOR = "_"; - - public static ImmutablePair getMetricNameAggregation(String alias) { - Preconditions.checkArgument(alias.contains(FUNCTION_NAME_SEPARATOR)); - - int index = alias.indexOf(FUNCTION_NAME_SEPARATOR); - return new ImmutablePair<>( - alias.substring(index + 1), FunctionType.valueOf(alias.substring(0, index))); - } - /** * Given the selection expressions, returns a map from the metric name/alias to the Aggregation * function that was requested. This will be useful to parse the results. @@ -36,23 +24,15 @@ public static Map getAggMetricToFunction( Map result = new HashMap<>(); for (Expression expression : selections) { if (expression.getValueCase() == ValueCase.FUNCTION) { - result.put(getAggregationFunctionAlias(expression.getFunction()), expression.getFunction()); + result.put( + ExpressionReader.getSelectionResultName(expression).orElseThrow(), + expression.getFunction()); } } return result; } - public static String getAggregationFunctionAlias(FunctionExpression functionExpression) { - if (StringUtils.isNotEmpty(functionExpression.getAlias())) { - return functionExpression.getAlias(); - } else { - return functionExpression.getFunction() - + FUNCTION_NAME_SEPARATOR - + functionExpression.getArguments(0).getColumnIdentifier().getColumnName(); - } - } - - public static Map getValueTypeFromFunction( + public static Map getValueTypeForFunctionType( Map functionExpressionMap, Map attributeMetadataMap) { Map aliasToValueType = new HashMap<>(); @@ -60,30 +40,31 @@ public static Map getValueTypeFromFunction( String alias = entry.getKey(); FunctionExpression functionExpression = entry.getValue(); aliasToValueType.put( - alias, getValueTypeFromFunction(functionExpression, attributeMetadataMap)); + alias, getValueTypeForFunctionType(functionExpression, attributeMetadataMap)); } return aliasToValueType; } - public static AttributeKind getValueTypeFromFunction( + public static AttributeKind getValueTypeForFunctionType( FunctionExpression functionExpression, Map attributeMetadataMap) { // assumes 1 level of aggregation for now, like the rest of the code // Also, for the type, it should follow the outer most aggregation type - String attributeName = - functionExpression.getArgumentsList().stream() - .filter(e -> e.getValueCase() == ValueCase.COLUMNIDENTIFIER) - .map(e -> e.getColumnIdentifier().getColumnName()) - .findFirst() + String attributeId = + ExpressionReader.getAttributeIdFromAttributeSelection(functionExpression) .orElseThrow(); // Should have validated the FunctionExpression using // AggregationValidator - AttributeMetadata metadata = attributeMetadataMap.get(attributeName); + AttributeMetadata metadata = attributeMetadataMap.get(attributeId); Preconditions.checkArgument( metadata != null, "Failed to find value type for this function because it is unable to find the metadata for %s", - attributeName); + attributeId); + + return getValueTypeForFunctionType(functionExpression.getFunction(), metadata); + } - FunctionType functionType = functionExpression.getFunction(); + public static AttributeKind getValueTypeForFunctionType( + FunctionType functionType, AttributeMetadata attributeMetadata) { switch (functionType) { case COUNT: case DISTINCTCOUNT: @@ -91,16 +72,16 @@ public static AttributeKind getValueTypeFromFunction( case MIN: case MAX: case SUM: - AttributeKind attributeKind = metadata.getValueKind(); + AttributeKind attributeKind = attributeMetadata.getValueKind(); // Min/Max/Sum function only applicable to numerical data Preconditions.checkArgument( AttributeKind.TYPE_DOUBLE.equals(attributeKind) || AttributeKind.TYPE_INT64.equals(attributeKind), "Incompatible data type for this function. Function : %s," - + " Attribute Kind: %s. Attribute Name : %s", + + " Attribute Kind: %s. Attribute ID : %s", functionType.name(), attributeKind.name(), - attributeName); + attributeMetadata.getId()); return attributeKind; case AVGRATE: @@ -108,7 +89,7 @@ public static AttributeKind getValueTypeFromFunction( case PERCENTILE: return AttributeKind.TYPE_DOUBLE; default: - return metadata.getValueKind(); + return attributeMetadata.getValueKind(); } } } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/OrderByUtil.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/OrderByUtil.java index ae272cb9..f5ebd8f1 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/OrderByUtil.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/OrderByUtil.java @@ -93,7 +93,7 @@ private static boolean orderByFunctionMatchesSelectionFunction( FunctionExpression orderByExpression, FunctionExpression selectionExpression) { Optional orderByColumnIdExpression = orderByExpression.getArgumentsList().stream() - .filter(Expression::hasColumnIdentifier) + .filter(ExpressionReader::isAttributeSelection) .findFirst(); if (orderByColumnIdExpression.isEmpty()) { return false; @@ -102,7 +102,7 @@ private static boolean orderByFunctionMatchesSelectionFunction( // Match the ColumnId Expression return selectionExpression.getFunction() == orderByExpression.getFunction() && selectionExpression.getArgumentsList().stream() - .filter(Expression::hasColumnIdentifier) + .filter(ExpressionReader::isAttributeSelection) .findFirst() .equals(orderByColumnIdExpression); } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/QueryExpressionUtil.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/QueryExpressionUtil.java index dce7260d..82aa8b36 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/QueryExpressionUtil.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/QueryExpressionUtil.java @@ -3,7 +3,7 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; -import org.hypertrace.gateway.service.v1.common.ColumnIdentifier; +import org.hypertrace.gateway.service.v1.common.AttributeExpression; import org.hypertrace.gateway.service.v1.common.Expression; import org.hypertrace.gateway.service.v1.common.Expression.Builder; import org.hypertrace.gateway.service.v1.common.Filter; @@ -19,9 +19,15 @@ public class QueryExpressionUtil { - public static Builder getColumnExpression(String columnName) { + public static Builder buildAttributeExpression(String attributeId) { return Expression.newBuilder() - .setColumnIdentifier(ColumnIdentifier.newBuilder().setColumnName(columnName)); + .setAttributeExpression(AttributeExpression.newBuilder().setAttributeId(attributeId)); + } + + public static Builder buildAttributeExpression(String attributeId, String alias) { + return Expression.newBuilder() + .setAttributeExpression( + AttributeExpression.newBuilder().setAttributeId(attributeId).setAlias(alias)); } public static Expression.Builder getLiteralExpression(String value) { @@ -51,7 +57,7 @@ public static Expression.Builder getAggregateFunctionExpression( } public static Expression.Builder getAggregateFunctionExpression( - String columnName, + String attributeId, FunctionType function, String alias, List additionalArguments, @@ -60,7 +66,7 @@ public static Expression.Builder getAggregateFunctionExpression( FunctionExpression.newBuilder() .setFunction(function) .setAlias(alias) - .addArguments(getColumnExpression(columnName)); + .addArguments(buildAttributeExpression(attributeId)); if (!additionalArguments.isEmpty()) { additionalArguments.forEach(functionBuilder::addArguments); } @@ -72,9 +78,9 @@ public static Expression.Builder getAggregateFunctionExpression( return Expression.newBuilder().setFunction(functionBuilder.build()); } - public static Filter.Builder getBooleanFilter(String columnName, boolean value) { + public static Filter.Builder getBooleanFilter(String attributeId, boolean value) { return Filter.newBuilder() - .setLhs(getColumnExpression(columnName)) + .setLhs(buildAttributeExpression(attributeId)) .setOperator(Operator.EQ) .setRhs( Expression.newBuilder() @@ -89,25 +95,12 @@ public static Filter.Builder getBooleanFilter(String columnName, boolean value) .build()); } - public static Filter.Builder getSimpleFilter(String columnName, String value) { - return Filter.newBuilder() - .setLhs(getColumnExpression(columnName)) - .setOperator(Operator.EQ) - .setRhs(getLiteralExpression(value)); - } - - public static Filter.Builder getSimpleNeqFilter(String columnName, String value) { + public static Filter buildStringFilter(String attributeId, Operator operator, String value) { return Filter.newBuilder() - .setLhs(getColumnExpression(columnName)) - .setOperator(Operator.NEQ) - .setRhs(getLiteralExpression(value)); - } - - public static Filter.Builder getLikeFilter(String columnName, String value) { - return Filter.newBuilder() - .setLhs(getColumnExpression(columnName)) - .setOperator(Operator.LIKE) - .setRhs(getLiteralExpression(value)); + .setLhs(buildAttributeExpression(attributeId)) + .setOperator(operator) + .setRhs(getLiteralExpression(value)) + .build(); } public static OrderByExpression.Builder getOrderBy( @@ -120,25 +113,7 @@ public static OrderByExpression.Builder getOrderBy( public static OrderByExpression.Builder getOrderBy(String columnName, SortOrder order) { return OrderByExpression.newBuilder() .setOrder(order) - .setExpression(getColumnExpression(columnName)); - } - - public static Filter createTimeFilter(String columnName, Operator op, long value) { - - ColumnIdentifier startTimeColumn = - ColumnIdentifier.newBuilder().setColumnName(columnName).build(); - Expression lhs = Expression.newBuilder().setColumnIdentifier(startTimeColumn).build(); - - LiteralConstant constant = - LiteralConstant.newBuilder() - .setValue( - Value.newBuilder() - .setString(String.valueOf(value)) - .setValueType(ValueType.STRING) - .build()) - .build(); - Expression rhs = Expression.newBuilder().setLiteral(constant).build(); - return Filter.newBuilder().setLhs(lhs).setOperator(op).setRhs(rhs).build(); + .setExpression(buildAttributeExpression(columnName)); } public static long alignToPeriodBoundary(long timeMillis, long periodSecs, boolean alignToNext) { diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/TimeRangeFilterUtil.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/TimeRangeFilterUtil.java index d617e892..060431e2 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/TimeRangeFilterUtil.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/util/TimeRangeFilterUtil.java @@ -2,7 +2,6 @@ import static org.hypertrace.gateway.service.v1.common.Operator.AND; -import org.hypertrace.gateway.service.v1.common.ColumnIdentifier; import org.hypertrace.gateway.service.v1.common.Expression; import org.hypertrace.gateway.service.v1.common.Filter; import org.hypertrace.gateway.service.v1.common.LiteralConstant; @@ -23,12 +22,10 @@ public static Filter addTimeRangeFilter( return filterBuilder.build(); } - private static Filter getTimestampFilter(String colName, Operator operator, long timestamp) { + private static Filter getTimestampFilter(String attributeId, Operator operator, long timestamp) { return Filter.newBuilder() .setOperator(operator) - .setLhs( - Expression.newBuilder() - .setColumnIdentifier(ColumnIdentifier.newBuilder().setColumnName(colName))) + .setLhs(QueryExpressionUtil.buildAttributeExpression(attributeId)) .setRhs( Expression.newBuilder() .setLiteral( diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/function/AvgRateValidator.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/function/AvgRateValidator.java index f2283d45..cce93ce4 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/function/AvgRateValidator.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/function/AvgRateValidator.java @@ -1,10 +1,13 @@ package org.hypertrace.gateway.service.common.validators.function; +import static java.util.function.Predicate.not; import static org.hypertrace.gateway.service.v1.common.Expression.ValueCase.HEALTH; import java.time.Duration; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoUnit; +import java.util.Optional; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.v1.common.FunctionExpression; import org.hypertrace.gateway.service.v1.common.FunctionType; import org.hypertrace.gateway.service.v1.common.ValueType; @@ -22,15 +25,18 @@ protected void validateArguments(FunctionExpression functionExpression) { functionExpression.getFunction()); var argumentsList = functionExpression.getArgumentsList(); - boolean columnIdentifierArgSet = false; + boolean attributeIdArgSet = false; boolean periodArgSet = false; for (var argument : argumentsList) { switch (argument.getValueCase()) { case COLUMNIDENTIFIER: - // Need a non empty column name - String columnName = argument.getColumnIdentifier().getColumnName(); - checkArgument(columnName != null && !columnName.isEmpty(), "columnName is null or empty"); - columnIdentifierArgSet = true; + case ATTRIBUTE_EXPRESSION: + // Need a non empty attribute ID + Optional attributeId = + ExpressionReader.getAttributeIdFromAttributeSelection(argument); + checkArgument( + attributeId.filter(not(String::isEmpty)).isPresent(), "attributeId is missing"); + attributeIdArgSet = true; break; case LITERAL: // Need the Period to be set in ISO format @@ -59,7 +65,7 @@ protected void validateArguments(FunctionExpression functionExpression) { } } - checkArgument(columnIdentifierArgSet, "ColumnIdentifier arg not set"); + checkArgument(attributeIdArgSet, "Attribute ID arg not set"); checkArgument(periodArgSet, "Period arg not set"); } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/function/OneArgAggregationValidator.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/function/OneArgAggregationValidator.java index 1006707c..f7e00460 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/function/OneArgAggregationValidator.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/function/OneArgAggregationValidator.java @@ -1,7 +1,10 @@ package org.hypertrace.gateway.service.common.validators.function; +import static java.util.function.Predicate.not; import static org.hypertrace.gateway.service.v1.common.Expression.ValueCase.HEALTH; +import java.util.Optional; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.v1.common.FunctionExpression; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,14 +15,17 @@ public class OneArgAggregationValidator extends FunctionExpressionValidator { @Override protected void validateArguments(FunctionExpression functionExpression) { var argumentsList = functionExpression.getArgumentsList(); - boolean columnIdentifierArgSet = false; + boolean attributeIdArgSet = false; for (var argument : argumentsList) { switch (argument.getValueCase()) { case COLUMNIDENTIFIER: - // Need a non empty column name - String columnName = argument.getColumnIdentifier().getColumnName(); - checkArgument(columnName != null && !columnName.isEmpty(), "columnName is null or empty"); - columnIdentifierArgSet = true; + case ATTRIBUTE_EXPRESSION: + // Need a non empty attribute ID + Optional attributeId = + ExpressionReader.getAttributeIdFromAttributeSelection(argument); + checkArgument( + attributeId.filter(not(String::isEmpty)).isPresent(), "attributeId is missing"); + attributeIdArgSet = true; break; default: // Only other argument allowed is Health. All others are illegal. @@ -27,7 +33,7 @@ protected void validateArguments(FunctionExpression functionExpression) { } } - checkArgument(columnIdentifierArgSet, "ColumnIdentifier arg not set"); + checkArgument(attributeIdArgSet, "AttributeId arg not set"); } @Override diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/function/PercentileValidator.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/function/PercentileValidator.java index ec9efb39..3843b9b6 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/function/PercentileValidator.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/function/PercentileValidator.java @@ -1,7 +1,10 @@ package org.hypertrace.gateway.service.common.validators.function; +import static java.util.function.Predicate.not; import static org.hypertrace.gateway.service.v1.common.Expression.ValueCase.HEALTH; +import java.util.Optional; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.v1.common.FunctionExpression; import org.hypertrace.gateway.service.v1.common.FunctionType; import org.hypertrace.gateway.service.v1.common.LiteralConstant; @@ -20,15 +23,18 @@ protected void validateArguments(FunctionExpression functionExpression) { functionExpression.getFunction()); var argumentsList = functionExpression.getArgumentsList(); - boolean columnIdentifierArgSet = false; + boolean attributeIdArgSet = false; boolean percentileArgSet = false; for (var argument : argumentsList) { switch (argument.getValueCase()) { case COLUMNIDENTIFIER: - // Need a non empty column name - String columnName = argument.getColumnIdentifier().getColumnName(); - checkArgument(columnName != null && !columnName.isEmpty(), "columnName is null or empty"); - columnIdentifierArgSet = true; + case ATTRIBUTE_EXPRESSION: + // Need a non empty attribute ID + Optional attributeId = + ExpressionReader.getAttributeIdFromAttributeSelection(argument); + checkArgument( + attributeId.filter(not(String::isEmpty)).isPresent(), "attributeId is missing"); + attributeIdArgSet = true; break; case LITERAL: // Need the percentile to be set @@ -43,7 +49,7 @@ protected void validateArguments(FunctionExpression functionExpression) { } } - checkArgument(columnIdentifierArgSet, "ColumnIdentifier arg not set"); + checkArgument(attributeIdArgSet, "ColumnIdentifier arg not set"); checkArgument(percentileArgSet, "Percentile arg not set"); } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/request/RequestValidator.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/request/RequestValidator.java index c2045319..a468691b 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/request/RequestValidator.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/common/validators/request/RequestValidator.java @@ -1,11 +1,10 @@ package org.hypertrace.gateway.service.common.validators.request; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.hypertrace.core.attribute.service.v1.AttributeMetadata; -import org.hypertrace.core.attribute.service.v1.AttributeType; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.common.validators.Validator; import org.hypertrace.gateway.service.common.validators.aggregation.TimeAggregationValidator; import org.hypertrace.gateway.service.common.validators.function.AggregationValidator; @@ -61,68 +60,16 @@ private void validateFunctionExpression( protected void validateSimpleSelections( List selections, Map attributeMetadataMap) { selections.stream() - .filter(expr -> expr.getValueCase() == Expression.ValueCase.COLUMNIDENTIFIER) + .filter(ExpressionReader::isAttributeSelection) .forEach(expression -> validateAttributeExists(attributeMetadataMap, expression)); } protected void validateAttributeExists( Map attributeMetadataMap, Expression expression) { - Set attributeNames = getAttributeNames(expression); - attributeNames.forEach( + Set attributeIds = ExpressionReader.extractAttributeIds(expression); + attributeIds.forEach( name -> checkArgument( attributeMetadataMap.containsKey(name), "Attribute {%s} not found", name)); } - - // This validation is too strong since some aggregatable attributes like duration are defined as - // ATTRIBUTE instead of METRIC - private void validateAggregationAtrribute( - Map attributeMetadataMap, Expression expression) { - Set attributeNames = getAttributeNames(expression); - attributeNames.forEach( - name -> { - checkArgument(attributeMetadataMap.containsKey(name), "Attribute {%s} not found", name); - checkArgument( - attributeMetadataMap.get(name).getType() == AttributeType.METRIC, - "Attribute {%s} must be of type {METRIC} but is of type {%s}", - name, - attributeMetadataMap.get(name).getType()); - }); - } - - private Set getAttributeNames(List expressions) { - Set attributeNames = new HashSet<>(); - expressions.forEach( - expr -> { - extractColumn(attributeNames, expr); - }); - return attributeNames; - } - - private Set getAttributeNames(Expression expression) { - Set attributeNames = new HashSet<>(); - extractColumn(attributeNames, expression); - return attributeNames; - } - - private void extractColumn( - Set columns, org.hypertrace.gateway.service.v1.common.Expression expression) { - switch (expression.getValueCase()) { - case COLUMNIDENTIFIER: - String columnName = expression.getColumnIdentifier().getColumnName(); - columns.add(columnName); - break; - case FUNCTION: - for (org.hypertrace.gateway.service.v1.common.Expression fexp : - expression.getFunction().getArgumentsList()) { - extractColumn(columns, fexp); - } - break; - case ORDERBY: - extractColumn(columns, expression.getOrderBy().getExpression()); - case LITERAL: - case VALUE_NOT_SET: - break; - } - } } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/EntityService.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/EntityService.java index 6809ea6e..bba0877c 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/EntityService.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/EntityService.java @@ -149,7 +149,7 @@ public EntitiesResponse getEntities( timestampAttributeId, requestHeaders); EntitiesRequest preProcessedRequest = - requestPreProcessor.transformFilter(originalRequest, entitiesRequestContext); + requestPreProcessor.process(originalRequest, entitiesRequestContext); ExecutionContext executionContext = ExecutionContext.from( diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/query/ExecutionContext.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/query/ExecutionContext.java index 42aa0ae6..811b4a19 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/query/ExecutionContext.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/query/ExecutionContext.java @@ -20,11 +20,11 @@ import org.hypertrace.gateway.service.common.util.AttributeMetadataUtil; import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.common.util.OrderByUtil; +import org.hypertrace.gateway.service.common.util.QueryExpressionUtil; import org.hypertrace.gateway.service.entity.EntitiesRequestContext; import org.hypertrace.gateway.service.entity.config.EntityIdColumnsConfigs; -import org.hypertrace.gateway.service.v1.common.ColumnIdentifier; import org.hypertrace.gateway.service.v1.common.Expression; -import org.hypertrace.gateway.service.v1.common.Expression.ValueCase; +import org.hypertrace.gateway.service.v1.common.Expression.Builder; import org.hypertrace.gateway.service.v1.common.Filter; import org.hypertrace.gateway.service.v1.common.OrderByExpression; import org.hypertrace.gateway.service.v1.common.TimeAggregation; @@ -195,13 +195,9 @@ public List getEntityIdExpressions() { return IntStream.range(0, entityIdAttributeNames.size()) .mapToObj( value -> - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder() - .setColumnName(entityIdAttributeNames.get(value)) - .setAlias("entityId" + value) - .build()) - .build()) + QueryExpressionUtil.buildAttributeExpression( + entityIdAttributeNames.get(value), "entityId" + value)) + .map(Builder::build) .collect(Collectors.toList()); } @@ -224,7 +220,8 @@ public void removeSelectionAttributes(String source, Set attributes) { Predicate retainExpressionPredicate = expression -> - Sets.intersection(ExpressionReader.extractColumns(expression), attributes).isEmpty(); + Sets.intersection(ExpressionReader.extractAttributeIds(expression), attributes) + .isEmpty(); List expressions = sourceToSelectionExpressionMap.get(source).stream() .filter(retainExpressionPredicate) @@ -262,15 +259,17 @@ public Map> getAllAttributesToSourcesMap() { } private void buildSourceToExpressionMaps() { - Map> selectionExprTypeToExprMap = + List attributeSelections = entitiesRequest.getSelectionList().stream() - .collect(Collectors.groupingBy(Expression::getValueCase, Collectors.toList())); - sourceToSelectionExpressionMap = - getDataSourceToExpressionMap(selectionExprTypeToExprMap.get(ValueCase.COLUMNIDENTIFIER)); + .filter(ExpressionReader::isAttributeSelection) + .collect(Collectors.toUnmodifiableList()); + sourceToSelectionExpressionMap = getDataSourceToExpressionMap(attributeSelections); sourceToSelectionAttributeMap = buildSourceToAttributesMap(sourceToSelectionExpressionMap); - - sourceToMetricExpressionMap = - getDataSourceToExpressionMap(selectionExprTypeToExprMap.get(ValueCase.FUNCTION)); + List functionSelections = + entitiesRequest.getSelectionList().stream() + .filter(Expression::hasFunction) + .collect(Collectors.toUnmodifiableList()); + sourceToMetricExpressionMap = getDataSourceToExpressionMap(functionSelections); sourceToTimeAggregationMap = getDataSourceToTimeAggregation(entitiesRequest.getTimeAggregationList()); pendingSelectionSources.addAll(sourceToSelectionExpressionMap.keySet()); @@ -296,24 +295,27 @@ private void buildSourceToOrderByExpressionMaps() { entitiesRequest.getOrderByList(), entitiesRequest.getSelectionList(), entitiesRequest.getTimeAggregationList()); - Map> orderByExpressionTypeToExpressionMap = + + List attributeOrderByExpressions = orderByExpressions.stream() - .collect( - Collectors.groupingBy( - orderByExpression -> orderByExpression.getExpression().getValueCase(), - Collectors.toList())); + .filter( + orderByExpression -> + ExpressionReader.isAttributeSelection(orderByExpression.getExpression())) + .collect(Collectors.toUnmodifiableList()); + sourceToSelectionOrderByExpressionMap = - getDataSourceToOrderByExpressionMap( - orderByExpressionTypeToExpressionMap.getOrDefault( - ValueCase.COLUMNIDENTIFIER, Collections.emptyList())); + getDataSourceToOrderByExpressionMap(attributeOrderByExpressions); sourceToSelectionOrderByAttributeMap = buildSourceToAttributesMap( convertOrderByExpressionToExpression(sourceToSelectionOrderByExpressionMap)); + List functionOrderByExpressions = + orderByExpressions.stream() + .filter(orderByExpression -> orderByExpression.getExpression().hasFunction()) + .collect(Collectors.toUnmodifiableList()); + sourceToMetricOrderByExpressionMap = - getDataSourceToOrderByExpressionMap( - orderByExpressionTypeToExpressionMap.getOrDefault( - ValueCase.FUNCTION, Collections.emptyList())); + getDataSourceToOrderByExpressionMap(functionOrderByExpressions); sourceToMetricOrderByAttributeMap = buildSourceToAttributesMap( convertOrderByExpressionToExpression(sourceToMetricOrderByExpressionMap)); @@ -397,14 +399,14 @@ private ImmutableMap> getDataSourceToExpressionMap( attributeMetadataProvider.getAttributesMetadata( this.entitiesRequestContext, entitiesRequest.getEntityType()); for (Expression expression : expressions) { - Set columnNames = ExpressionReader.extractColumns(expression); + Set attributeIds = ExpressionReader.extractAttributeIds(expression); Set sources = Arrays.stream(AttributeSource.values()).collect(Collectors.toSet()); - for (String columnName : columnNames) { - List sourcesList = attrNameToMetadataMap.get(columnName).getSourcesList(); + for (String attributeId : attributeIds) { + List sourcesList = attrNameToMetadataMap.get(attributeId).getSourcesList(); sources.retainAll(sourcesList); allAttributesToSourcesMap - .computeIfAbsent(columnName, v -> new HashSet<>()) + .computeIfAbsent(attributeId, v -> new HashSet<>()) .addAll(sourcesList.stream().map(Enum::name).collect(Collectors.toList())); } if (sources.isEmpty()) { @@ -434,7 +436,7 @@ private ImmutableMap> buildSourceToAttributesMap( Map.Entry::getKey, entry -> entry.getValue().stream() - .map(ExpressionReader::extractColumns) + .map(ExpressionReader::extractAttributeIds) .flatMap(Collection::stream) .collect(Collectors.toSet())))) .build(); diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/query/ExecutionTreeBuilder.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/query/ExecutionTreeBuilder.java index 676c2035..127370ee 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/query/ExecutionTreeBuilder.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/query/ExecutionTreeBuilder.java @@ -13,6 +13,7 @@ import java.util.stream.Stream; import org.hypertrace.core.attribute.service.v1.AttributeMetadata; import org.hypertrace.core.attribute.service.v1.AttributeSource; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.common.util.TimeRangeFilterUtil; import org.hypertrace.gateway.service.entity.query.visitor.ExecutionContextBuilderVisitor; import org.hypertrace.gateway.service.entity.query.visitor.FilterOptimizingVisitor; @@ -282,7 +283,9 @@ QueryNode buildFilterTree(EntitiesRequest entitiesRequest, Filter filter) { } else { List sources = attributeMetadataMap - .get(filter.getLhs().getColumnIdentifier().getColumnName()) + .get( + ExpressionReader.getAttributeIdFromAttributeSelection(filter.getLhs()) + .orElseThrow()) .getSourcesList(); // if the filter by and order by are from QS, pagination can be pushed down to QS diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/update/EdsEntityUpdater.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/update/EdsEntityUpdater.java index 61cd68ad..76725105 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/update/EdsEntityUpdater.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/entity/update/EdsEntityUpdater.java @@ -1,15 +1,17 @@ package org.hypertrace.gateway.service.entity.update; import java.util.Iterator; +import java.util.Map; import java.util.stream.Collectors; +import org.hypertrace.core.attribute.service.v1.AttributeMetadata; import org.hypertrace.entity.query.service.client.EntityQueryServiceClient; -import org.hypertrace.entity.query.service.v1.ColumnMetadata; import org.hypertrace.entity.query.service.v1.EntityUpdateRequest; import org.hypertrace.entity.query.service.v1.ResultSetChunk; import org.hypertrace.entity.query.service.v1.Row; import org.hypertrace.entity.query.service.v1.SetAttribute; import org.hypertrace.entity.query.service.v1.UpdateOperation; import org.hypertrace.gateway.service.common.converters.EntityServiceAndGatewayServiceConverter; +import org.hypertrace.gateway.service.common.util.AttributeMetadataUtil; import org.hypertrace.gateway.service.v1.entity.BulkUpdateEntitiesRequest; import org.hypertrace.gateway.service.v1.entity.BulkUpdateEntitiesResponse; import org.hypertrace.gateway.service.v1.entity.Entity; @@ -59,17 +61,18 @@ public UpdateEntityResponse.Builder update( "Received more than 1 row back. Only the first out of {} rows will be returned in the response", chunk.getRowCount()); } - + Map resultAttributeMetadata = + AttributeMetadataUtil.remapAttributeMetadataByResultKey( + updateRequest.getSelectionList(), updateExecutionContext.getAttributeMetadata()); Row row = chunk.getRow(0); Entity.Builder entityBuilder = Entity.newBuilder().setEntityType(updateRequest.getEntityType()); for (int i = 0; i < chunk.getResultSetMetadata().getColumnMetadataCount(); i++) { - ColumnMetadata metadata = chunk.getResultSetMetadata().getColumnMetadata(i); - String attributeName = metadata.getColumnName(); + String resultName = chunk.getResultSetMetadata().getColumnMetadata(i).getColumnName(); entityBuilder.putAttribute( - attributeName, - EntityServiceAndGatewayServiceConverter.convertToGatewayValue( - attributeName, row.getColumn(i), updateExecutionContext.getAttributeMetadata())); + resultName, + EntityServiceAndGatewayServiceConverter.convertQueryValueToGatewayValue( + row.getColumn(i), resultAttributeMetadata.get(resultName))); } responseBuilder.setEntity(entityBuilder); diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/ExploreRequestValidator.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/ExploreRequestValidator.java index 62baaab6..68f59318 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/ExploreRequestValidator.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/ExploreRequestValidator.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Map; import org.hypertrace.core.attribute.service.v1.AttributeMetadata; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.common.validators.request.RequestValidator; import org.hypertrace.gateway.service.v1.common.Expression; import org.hypertrace.gateway.service.v1.common.Period; @@ -48,7 +49,7 @@ private void validateGroupBy( List selections, Map attributeMetadataMap) { checkArgument( - groupByExpressions.stream().allMatch(Expression::hasColumnIdentifier), + groupByExpressions.stream().allMatch(ExpressionReader::isAttributeSelection), "Group By expressions should all be on columns(for now)."); validateSimpleSelections(groupByExpressions, attributeMetadataMap); @@ -82,7 +83,7 @@ private void validateEitherSelectionsOrTimeAggregations(ExploreRequest request) private void validateAllSelectionsAreEitherColumnOrAggregations(List selections) { checkArgument( - selections.stream().allMatch(Expression::hasColumnIdentifier) + selections.stream().allMatch(ExpressionReader::isAttributeSelection) || selections.stream().allMatch(Expression::hasFunction), "The selections should either be all columns or all aggregations"); } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/RequestHandler.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/RequestHandler.java index 63a7e1a0..bb670209 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/RequestHandler.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/RequestHandler.java @@ -6,7 +6,6 @@ import java.util.List; import java.util.Map; import org.hypertrace.core.attribute.service.v1.AttributeMetadata; -import org.hypertrace.core.query.service.api.ColumnIdentifier; import org.hypertrace.core.query.service.api.ColumnMetadata; import org.hypertrace.core.query.service.api.Filter; import org.hypertrace.core.query.service.api.QueryRequest; @@ -74,7 +73,7 @@ QueryRequest buildQueryRequest( // 1. Add selections. All selections should either be only column or only function, never both. // The validator should catch this. List aggregatedSelections = - ExpressionReader.getFunctionExpressions(request.getSelectionList().stream()); + ExpressionReader.getFunctionExpressions(request.getSelectionList()); aggregatedSelections.forEach( aggregatedSelection -> { requestContext.mapAliasToFunctionExpression( @@ -84,7 +83,7 @@ QueryRequest buildQueryRequest( }); List columnSelections = - ExpressionReader.getColumnExpressions(request.getSelectionList().stream()); + ExpressionReader.getAttributeExpressions(request.getSelectionList()); columnSelections.forEach( columnSelection -> builder.addSelection( @@ -171,18 +170,12 @@ public List getRequestOrderByExpressions(ExploreRequest reque } private void addGroupByExpressionToBuilder(QueryRequest.Builder builder, Expression expression) { - org.hypertrace.core.query.service.api.Expression.Builder expressionBuilder = - org.hypertrace.core.query.service.api.Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder() - .setColumnName(expression.getColumnIdentifier().getColumnName()) - .setAlias(expression.getColumnIdentifier().getAlias())); // Add groupBy expression to GroupBy list - builder.addGroupBy(expressionBuilder); + builder.addGroupBy(QueryAndGatewayDtoConverter.convertToQueryExpression(expression)); // Add groupBy to Selection list. The expectation from the Gateway service client is that they // do not add the // group by expressions to the selection expressions in the request - builder.addSelection(expressionBuilder); + builder.addSelection(QueryAndGatewayDtoConverter.convertToQueryExpression(expression)); } private ExploreResponse.Builder handleQueryServiceResponse( @@ -282,7 +275,7 @@ void handleQueryServiceResponseSingleColumn( if (function != null) { // Function expression value gwValue = QueryAndGatewayDtoConverter.convertToGatewayValueForMetricValue( - MetricAggregationFunctionUtil.getValueTypeFromFunction( + MetricAggregationFunctionUtil.getValueTypeForFunctionType( function, attributeMetadataMap), attributeMetadataMap, metadata, diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/TheRestGroupRequestHandler.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/TheRestGroupRequestHandler.java index 55bdb581..963fd535 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/TheRestGroupRequestHandler.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/TheRestGroupRequestHandler.java @@ -2,9 +2,11 @@ import com.google.common.collect.ImmutableSet; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; -import org.hypertrace.gateway.service.v1.common.ColumnIdentifier; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.v1.common.Expression; import org.hypertrace.gateway.service.v1.common.Filter; import org.hypertrace.gateway.service.v1.common.LiteralConstant; @@ -131,9 +133,10 @@ private Filter.Builder createExcludeFoundGroupsNotInListFilter( .getGroupByList() .forEach( groupBy -> { - String columnName = groupBy.getColumnIdentifier().getColumnName(); - Set excludedValues = getExcludedValues(columnName, originalResponse); - filterBuilder.addChildFilter(createExcludedChildFilter(columnName, excludedValues)); + String groupByResultName = + ExpressionReader.getSelectionResultName(groupBy).orElseThrow(); + Set excludedValues = getExcludedValues(groupByResultName, originalResponse); + filterBuilder.addChildFilter(createExcludedChildFilter(groupBy, excludedValues)); }); return filterBuilder; @@ -168,39 +171,40 @@ private Filter.Builder createExcludeFoundGroupsAndChainFilter( ExploreRequest originalRequest, ExploreResponse.Builder originalResponse) { Filter.Builder filterBuilder = Filter.newBuilder(); filterBuilder.setOperator(Operator.AND); - List groupByColumns = groupByColumnList(originalRequest); + Map groupBySelectionExpressionsByResultName = + groupByExpressionByResultName(originalRequest); originalResponse .getRowBuilderList() .forEach( rowBuilder -> filterBuilder.addChildFilter( - createGroupValuesOrFilter(groupByColumns, rowBuilder))); + createGroupValuesOrFilter( + groupBySelectionExpressionsByResultName, rowBuilder))); return filterBuilder; } - private List groupByColumnList(ExploreRequest originalRequest) { + private Map groupByExpressionByResultName(ExploreRequest originalRequest) { return originalRequest.getGroupByList().stream() - .map(groupBy -> groupBy.getColumnIdentifier().getColumnName()) - .collect(Collectors.toUnmodifiableList()); + .collect( + Collectors.toUnmodifiableMap( + expression -> ExpressionReader.getSelectionResultName(expression).orElseThrow(), + Function.identity())); } private Filter.Builder createGroupValuesOrFilter( - List groupByColumns, Row.Builder rowBuilder) { + Map groupBySelectionExpressionsByResultName, Row.Builder rowBuilder) { Filter.Builder filterBuilder = Filter.newBuilder(); filterBuilder.setOperator(Operator.OR); rowBuilder .getColumnsMap() .forEach( (columnName, columnValue) -> { - if (groupByColumns.contains(columnName)) { + if (groupBySelectionExpressionsByResultName.containsKey(columnName)) { filterBuilder.addChildFilter( Filter.newBuilder() - .setLhs( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder().setColumnName(columnName))) + .setLhs(groupBySelectionExpressionsByResultName.get(columnName)) .setOperator(Operator.NEQ) .setRhs( Expression.newBuilder() @@ -217,19 +221,17 @@ private Filter.Builder createGroupValuesOrFilter( } private Set getExcludedValues( - String columnName, ExploreResponse.Builder originalResponse) { - // GroupBy only supports columns expressions for now. + String resultName, ExploreResponse.Builder originalResponse) { return originalResponse.getRowBuilderList().stream() - .map(rowBuilder -> rowBuilder.getColumnsMap().get(columnName)) + .map(rowBuilder -> rowBuilder.getColumnsMap().get(resultName)) .map(Value::getString) .collect(ImmutableSet.toImmutableSet()); } - private Filter.Builder createExcludedChildFilter(String columnName, Set excludedValues) { + private Filter.Builder createExcludedChildFilter( + Expression groupBySelectionExpression, Set excludedValues) { return Filter.newBuilder() - .setLhs( - Expression.newBuilder() - .setColumnIdentifier(ColumnIdentifier.newBuilder().setColumnName(columnName))) + .setLhs(groupBySelectionExpression) .setOperator(Operator.NOT_IN) .setRhs( Expression.newBuilder() @@ -257,14 +259,12 @@ private void mergeTheRestResponseIntoOriginalResponse( private void appendTheRestColumnValueToRowBuilder( Row.Builder rowBuilder, List groupBys) { groupBys.forEach( - groupBy -> { - String columnName = groupBy.getColumnIdentifier().getColumnName(); - rowBuilder.putColumns( - columnName, - Value.newBuilder() - .setValueType(ValueType.STRING) - .setString(OTHER_COLUMN_VALUE) - .build()); - }); + groupBy -> + rowBuilder.putColumns( + ExpressionReader.getSelectionResultName(groupBy).orElseThrow(), + Value.newBuilder() + .setValueType(ValueType.STRING) + .setString(OTHER_COLUMN_VALUE) + .build())); } } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/TimeAggregationsRequestHandler.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/TimeAggregationsRequestHandler.java index ccc3f4dc..471fa3cb 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/TimeAggregationsRequestHandler.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/TimeAggregationsRequestHandler.java @@ -6,6 +6,7 @@ import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import org.hypertrace.core.query.service.api.ColumnMetadata; import org.hypertrace.core.query.service.api.QueryRequest; import org.hypertrace.core.query.service.api.ResultSetMetadata; @@ -15,9 +16,8 @@ import org.hypertrace.gateway.service.common.AttributeMetadataProvider; import org.hypertrace.gateway.service.common.converters.QueryAndGatewayDtoConverter; import org.hypertrace.gateway.service.common.util.AttributeMetadataUtil; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.common.util.QueryExpressionUtil; -import org.hypertrace.gateway.service.v1.common.ColumnIdentifier; -import org.hypertrace.gateway.service.v1.common.Expression; import org.hypertrace.gateway.service.v1.common.OrderByExpression; import org.hypertrace.gateway.service.v1.common.Period; import org.hypertrace.gateway.service.v1.common.SortOrder; @@ -93,10 +93,8 @@ public List getRequestOrderByExpressions(ExploreRequest reque OrderByExpression.newBuilder() .setOrder(SortOrder.ASC) .setExpression( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder() - .setColumnName(ColumnName.INTERVAL_START_TIME.name()))) + QueryExpressionUtil.buildAttributeExpression( + ColumnName.INTERVAL_START_TIME.name())) .build(); resolvedOrderBys.add(defaultIntervalOrdering); @@ -110,8 +108,8 @@ public List getRequestOrderByExpressions(ExploreRequest reque private boolean containsIntervalOrdering(List orderByExpressions) { return orderByExpressions.stream() .map(OrderByExpression::getExpression) - .map(Expression::getColumnIdentifier) - .map(ColumnIdentifier::getColumnName) + .map(ExpressionReader::getAttributeIdFromAttributeSelection) + .flatMap(Optional::stream) .anyMatch(name -> name.equals(ColumnName.INTERVAL_START_TIME.name())); } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/TimeAggregationsWithGroupByRequestHandler.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/TimeAggregationsWithGroupByRequestHandler.java index 113d4066..14676f58 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/TimeAggregationsWithGroupByRequestHandler.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/explore/TimeAggregationsWithGroupByRequestHandler.java @@ -4,7 +4,7 @@ import java.util.Set; import org.hypertrace.core.query.service.client.QueryServiceClient; import org.hypertrace.gateway.service.common.AttributeMetadataProvider; -import org.hypertrace.gateway.service.v1.common.ColumnIdentifier; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.v1.common.Expression; import org.hypertrace.gateway.service.v1.common.Filter; import org.hypertrace.gateway.service.v1.common.LiteralConstant; @@ -115,9 +115,10 @@ private Filter.Builder createInClauseFilterFromGroupByResults( .getGroupByList() .forEach( groupBy -> { - String columnName = groupBy.getColumnIdentifier().getColumnName(); - Set inClauseValues = getInClauseValues(columnName, groupByResponse); - filterBuilder.addChildFilter(createInClauseChildFilter(columnName, inClauseValues)); + String groupByResultName = + ExpressionReader.getSelectionResultName(groupBy).orElseThrow(); + Set inClauseValues = getInClauseValues(groupByResultName, groupByResponse); + filterBuilder.addChildFilter(createInClauseChildFilter(groupBy, inClauseValues)); }); return filterBuilder; @@ -131,11 +132,10 @@ private Set getInClauseValues( .collect(ImmutableSet.toImmutableSet()); } - private Filter.Builder createInClauseChildFilter(String columnName, Set inClauseValues) { + private Filter.Builder createInClauseChildFilter( + Expression groupBySelectionExpression, Set inClauseValues) { return Filter.newBuilder() - .setLhs( - Expression.newBuilder() - .setColumnIdentifier(ColumnIdentifier.newBuilder().setColumnName(columnName))) + .setLhs(groupBySelectionExpression) .setOperator(Operator.IN) .setRhs( Expression.newBuilder() diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/logevent/LogEventsService.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/logevent/LogEventsService.java index 5ae5e8d0..b63d72b0 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/logevent/LogEventsService.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/logevent/LogEventsService.java @@ -22,6 +22,7 @@ import org.hypertrace.gateway.service.common.AttributeMetadataProvider; import org.hypertrace.gateway.service.common.RequestContext; import org.hypertrace.gateway.service.common.converters.QueryAndGatewayDtoConverter; +import org.hypertrace.gateway.service.common.util.AttributeMetadataUtil; import org.hypertrace.gateway.service.v1.common.OrderByExpression; import org.hypertrace.gateway.service.v1.log.events.LogEvent; import org.hypertrace.gateway.service.v1.log.events.LogEventsRequest; @@ -81,6 +82,10 @@ private List fetchLogEvents( LogEventsRequest request, Map attributeMetadataMap) { + Map resultKeyToAttributeMetadataMap = + AttributeMetadataUtil.remapAttributeMetadataByResultKey( + request.getSelectionList(), attributeMetadataMap); + AttributeMetadata timestampAttributeMetadata = getTimestampAttributeMetadata(attributeMetadataProvider, context, LOG_EVENT_SCOPE); QueryRequest.Builder queryBuilder = @@ -131,7 +136,7 @@ private List fetchLogEvents( logEventBuilder.putAttributes( metadata.getColumnName(), QueryAndGatewayDtoConverter.convertToGatewayValue( - attrName, row.getColumn(i), attributeMetadataMap)); + attrName, row.getColumn(i), resultKeyToAttributeMetadataMap)); } logEventResult.add(logEventBuilder.build()); diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/span/SpanService.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/span/SpanService.java index 95c0020c..6d89b8b2 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/span/SpanService.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/span/SpanService.java @@ -27,6 +27,7 @@ import org.hypertrace.gateway.service.common.AttributeMetadataProvider; import org.hypertrace.gateway.service.common.RequestContext; import org.hypertrace.gateway.service.common.converters.QueryAndGatewayDtoConverter; +import org.hypertrace.gateway.service.common.util.AttributeMetadataUtil; import org.hypertrace.gateway.service.v1.common.OrderByExpression; import org.hypertrace.gateway.service.v1.span.SpanEvent; import org.hypertrace.gateway.service.v1.span.SpansRequest; @@ -98,6 +99,10 @@ List filterSpanEvents( SpansRequest request, Map attributeMetadataMap) { + Map resultKeyToAttributeMetadataMap = + AttributeMetadataUtil.remapAttributeMetadataByResultKey( + request.getSelectionList(), attributeMetadataMap); + QueryRequest.Builder queryBuilder = createQueryWithFilter(request, context); if (!request.getSelectionList().isEmpty()) { @@ -133,7 +138,7 @@ List filterSpanEvents( spanEventBuilder.putAttributes( metadata.getColumnName(), QueryAndGatewayDtoConverter.convertToGatewayValue( - attrName, row.getColumn(i), attributeMetadataMap)); + attrName, row.getColumn(i), resultKeyToAttributeMetadataMap)); } spanEventsResult.add(spanEventBuilder.build()); diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/trace/TraceComparator.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/trace/TraceComparator.java index 8da88c8f..946230b2 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/trace/TraceComparator.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/trace/TraceComparator.java @@ -4,6 +4,7 @@ import java.util.Comparator; import java.util.List; import org.apache.commons.lang3.StringUtils; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.v1.common.OrderByExpression; import org.hypertrace.gateway.service.v1.common.SortOrder; import org.hypertrace.gateway.service.v1.common.Value; @@ -29,10 +30,13 @@ public int compare(Trace.Builder left, Trace.Builder right) { "Invalid orderBy: " + orderBy.getExpression().getValueCase()); case COLUMNIDENTIFIER: - // Otherwise, this is either a simple attribute/metric or entity name itself. - String attr = orderBy.getExpression().getColumnIdentifier().getColumnName(); - int value; - value = compare(left.getAttributesMap().get(attr), right.getAttributesMap().get(attr)); + case ATTRIBUTE_EXPRESSION: + String resultName = + ExpressionReader.getSelectionResultName(orderBy.getExpression()).orElseThrow(); + int value = + compare( + left.getAttributesMap().get(resultName), + right.getAttributesMap().get(resultName)); if (value == 0) { continue; } diff --git a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/trace/TracesService.java b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/trace/TracesService.java index 551f1cf1..228c4199 100644 --- a/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/trace/TracesService.java +++ b/gateway-service-impl/src/main/java/org/hypertrace/gateway/service/trace/TracesService.java @@ -29,6 +29,8 @@ import org.hypertrace.gateway.service.common.config.ScopeFilterConfigs; import org.hypertrace.gateway.service.common.converters.QueryAndGatewayDtoConverter; import org.hypertrace.gateway.service.common.transformer.RequestPreProcessor; +import org.hypertrace.gateway.service.common.util.AttributeMetadataUtil; +import org.hypertrace.gateway.service.common.util.ExpressionReader; import org.hypertrace.gateway.service.v1.common.OrderByExpression; import org.hypertrace.gateway.service.v1.trace.Trace; import org.hypertrace.gateway.service.v1.trace.TracesRequest; @@ -84,7 +86,7 @@ public TracesResponse getTracesByFilter(RequestContext context, TracesRequest re try { requestValidator.validateScope(request); - TracesRequest preProcessedRequest = requestPreProcessor.transformFilter(request, context); + TracesRequest preProcessedRequest = requestPreProcessor.process(request, context); TraceScope scope = TraceScope.valueOf(preProcessedRequest.getScope()); Map attributeMap = @@ -120,6 +122,10 @@ List filterTraces( Map attributeMetadataMap, TraceScope scope) { + Map resultKeyToAttributeMetadataMap = + AttributeMetadataUtil.remapAttributeMetadataByResultKey( + request.getSelectionList(), attributeMetadataMap); + QueryRequest.Builder builder = createQueryWithFilter(request, scope, context); if (!request.getSelectionList().isEmpty()) { @@ -157,7 +163,7 @@ List filterTraces( traceBuilder.putAttributes( metadata.getColumnName(), QueryAndGatewayDtoConverter.convertToGatewayValue( - attrName, row.getColumn(i), attributeMetadataMap)); + attrName, row.getColumn(i), resultKeyToAttributeMetadataMap)); } tracesResult.add(traceBuilder.build()); @@ -174,8 +180,10 @@ int getTotalFilteredTraces(RequestContext context, TracesRequest request, TraceS throw new IllegalArgumentException("Query request does not have any selection"); } - String columnName = request.getSelection(0).getColumnIdentifier().getColumnName(); - queryBuilder.addSelection(createCountByColumnSelection(columnName)); + String firstSelectionAttributeId = + ExpressionReader.getAttributeIdFromAttributeSelection(request.getSelection(0)) + .orElseThrow(); + queryBuilder.addSelection(createCountByColumnSelection(firstSelectionAttributeId)); QueryRequest queryRequest = queryBuilder.build(); Iterator resultSetChunkIterator = queryServiceClient.executeQuery(queryRequest, context.getHeaders(), queryServiceReqTimeout); diff --git a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/QueryServiceRequestAndResponseUtils.java b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/QueryServiceRequestAndResponseUtils.java index 0d33d73d..80a648e8 100644 --- a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/QueryServiceRequestAndResponseUtils.java +++ b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/QueryServiceRequestAndResponseUtils.java @@ -1,7 +1,7 @@ package org.hypertrace.gateway.service.common; +import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createAttributeExpression; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createBetweenTimesFilter; -import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createColumnExpression; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createFilter; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createStringNullLiteralExpression; @@ -67,7 +67,7 @@ public static Expression createQsAggregationExpression( Function.newBuilder() .setFunctionName(functionName) .setAlias(functionAlias) - .addArguments(createColumnExpression(columnName, columnAlias))) + .addArguments(createAttributeExpression(columnName, columnAlias))) .build(); } @@ -78,7 +78,7 @@ public static Expression createQsAggregationExpression( Function.newBuilder() .setFunctionName(functionName) .setAlias(alias) - .addArguments(createColumnExpression(columnName))) + .addArguments(createAttributeExpression(columnName))) .build(); } @@ -87,7 +87,7 @@ public static Expression createQsAggregationExpression(String functionName, Stri .setFunction( Function.newBuilder() .setFunctionName(functionName) - .addArguments(createColumnExpression(columnName))) + .addArguments(createAttributeExpression(columnName))) .build(); } @@ -105,7 +105,7 @@ public static Filter createQsRequestFilter( .setOperator(Operator.AND) .addChildFilter( createFilter( - createColumnExpression(entityIdColumnName), + createAttributeExpression(entityIdColumnName), Operator.NEQ, createStringNullLiteralExpression())) .addChildFilter(createBetweenTimesFilter(timestampColumnName, startTime, endTime)) @@ -119,7 +119,7 @@ public static Filter createQsDefaultRequestFilter( .setOperator(Operator.AND) .addChildFilter( createFilter( - createColumnExpression(entityIdColumnName), + createAttributeExpression(entityIdColumnName), Operator.NEQ, createStringNullLiteralExpression())) .addAllChildFilter( diff --git a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/config/ScopeFilterConfigsTest.java b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/config/ScopeFilterConfigsTest.java index eef4a021..83840faa 100644 --- a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/config/ScopeFilterConfigsTest.java +++ b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/config/ScopeFilterConfigsTest.java @@ -1,5 +1,6 @@ package org.hypertrace.gateway.service.common.config; +import static org.hypertrace.gateway.service.common.util.QueryExpressionUtil.buildAttributeExpression; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -11,7 +12,6 @@ import org.hypertrace.core.attribute.service.v1.AttributeScope; import org.hypertrace.gateway.service.common.AttributeMetadataProvider; import org.hypertrace.gateway.service.common.RequestContext; -import org.hypertrace.gateway.service.v1.common.ColumnIdentifier; import org.hypertrace.gateway.service.v1.common.Expression; import org.hypertrace.gateway.service.v1.common.Filter; import org.hypertrace.gateway.service.v1.common.LiteralConstant; @@ -52,12 +52,12 @@ public void testScopeFilterConfig() { .setOperator(Operator.AND) .addChildFilter( Filter.newBuilder() - .setLhs(createColumnExpression("API_TRACE.id")) + .setLhs(buildAttributeExpression("API_TRACE.id")) .setOperator(Operator.EQ) .setRhs(createLiteralStringExpression("some-api-trace-id"))) .addChildFilter( Filter.newBuilder() - .setLhs(createColumnExpression("API_TRACE.some_col")) + .setLhs(buildAttributeExpression("API_TRACE.some_col")) .setOperator(Operator.EQ) .setRhs(createLiteralStringExpression("some-col-value"))) .build(); @@ -67,12 +67,12 @@ public void testScopeFilterConfig() { .setOperator(Operator.OR) .addChildFilter( Filter.newBuilder() - .setLhs(createColumnExpression("API_TRACE.id")) + .setLhs(buildAttributeExpression("API_TRACE.id")) .setOperator(Operator.EQ) .setRhs(createLiteralStringExpression("some-api-trace-id"))) .addChildFilter( Filter.newBuilder() - .setLhs(createColumnExpression("API_TRACE.some_col")) + .setLhs(buildAttributeExpression("API_TRACE.some_col")) .setOperator(Operator.EQ) .setRhs(createLiteralStringExpression("some-col-value"))) .build(); @@ -103,12 +103,12 @@ public void testScopeFilterConfig() { .setOperator(Operator.AND) .addChildFilter( Filter.newBuilder() - .setLhs(createColumnExpression("API_TRACE.apiBoundaryType")) + .setLhs(buildAttributeExpression("API_TRACE.apiBoundaryType")) .setOperator(Operator.EQ) .setRhs(createLiteralStringExpression("ENTRY"))) .addChildFilter( Filter.newBuilder() - .setLhs(createColumnExpression("API_TRACE.apiId")) + .setLhs(buildAttributeExpression("API_TRACE.apiId")) .setOperator(Operator.NEQ) .setRhs(createLiteralStringExpression("null"))); @@ -169,12 +169,12 @@ public void testScopeFilterConfigWithBogusOperator() { .setOperator(Operator.AND) .addChildFilter( Filter.newBuilder() - .setLhs(createColumnExpression("API_TRACE.id")) + .setLhs(buildAttributeExpression("API_TRACE.id")) .setOperator(Operator.EQ) .setRhs(createLiteralStringExpression("some-api-trace-id"))) .addChildFilter( Filter.newBuilder() - .setLhs(createColumnExpression("API_TRACE.some_col")) + .setLhs(buildAttributeExpression("API_TRACE.some_col")) .setOperator(Operator.EQ) .setRhs(createLiteralStringExpression("some-col-value"))) .build(); @@ -201,12 +201,12 @@ public void testEmptyScopeFilterConfig() { .setOperator(Operator.AND) .addChildFilter( Filter.newBuilder() - .setLhs(createColumnExpression("API_TRACE.id")) + .setLhs(buildAttributeExpression("API_TRACE.id")) .setOperator(Operator.EQ) .setRhs(createLiteralStringExpression("some-api-trace-id"))) .addChildFilter( Filter.newBuilder() - .setLhs(createColumnExpression("API_TRACE.some_col")) + .setLhs(buildAttributeExpression("API_TRACE.some_col")) .setOperator(Operator.EQ) .setRhs(createLiteralStringExpression("some-col-value"))) .build(); @@ -231,9 +231,4 @@ private Expression.Builder createLiteralStringExpression(String str) { LiteralConstant.newBuilder() .setValue(Value.newBuilder().setValueType(ValueType.STRING).setString(str))); } - - private Expression.Builder createColumnExpression(String columnName) { - return Expression.newBuilder() - .setColumnIdentifier(ColumnIdentifier.newBuilder().setColumnName(columnName)); - } } diff --git a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/converter/GatewayValueToQueryValueConverterTest.java b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/converter/GatewayValueToQueryValueConverterTest.java index 2099baf1..b46b1b13 100644 --- a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/converter/GatewayValueToQueryValueConverterTest.java +++ b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/converter/GatewayValueToQueryValueConverterTest.java @@ -5,8 +5,8 @@ import java.util.Map; import org.hypertrace.core.query.service.api.Function; import org.hypertrace.gateway.service.common.converters.QueryAndGatewayDtoConverter; +import org.hypertrace.gateway.service.common.converters.QueryRequestUtil; import org.hypertrace.gateway.service.common.util.QueryExpressionUtil; -import org.hypertrace.gateway.service.v1.common.ColumnIdentifier; import org.hypertrace.gateway.service.v1.common.Expression; import org.hypertrace.gateway.service.v1.common.Filter; import org.hypertrace.gateway.service.v1.common.FunctionExpression; @@ -89,12 +89,7 @@ public void testFilter() { private Map getOrderByExpressionMap() { org.hypertrace.core.query.service.api.Expression queryExpression = - org.hypertrace.core.query.service.api.Expression.newBuilder() - .setColumnIdentifier( - org.hypertrace.core.query.service.api.ColumnIdentifier.newBuilder() - .setColumnName("API.apiId") - .build()) - .build(); + QueryRequestUtil.createAttributeExpression("API.apiId"); Map expressionMap = new HashMap<>(); expressionMap.put( @@ -122,31 +117,16 @@ public void testFilter() { private Map getFilterMap() { Map filterMap = new HashMap<>(); - Filter.Builder gatewayFilterBuilder = - Filter.newBuilder() - .setLhs( - Expression.newBuilder() - .setColumnIdentifier(ColumnIdentifier.newBuilder().setColumnName("API.apiId"))) - .setRhs(Expression.newBuilder().setLiteral(getStringGatewayLiteralConstant("abc"))); - org.hypertrace.core.query.service.api.Filter.Builder queryFilterBuilder = - org.hypertrace.core.query.service.api.Filter.newBuilder() - .setLhs( - org.hypertrace.core.query.service.api.Expression.newBuilder() - .setColumnIdentifier( - org.hypertrace.core.query.service.api.ColumnIdentifier.newBuilder() - .setColumnName("API.apiId"))) - .setRhs( - org.hypertrace.core.query.service.api.Expression.newBuilder() - .setLiteral(getStringQueryLiteralConstant("abc"))); + Filter gatewayFilter = QueryExpressionUtil.buildStringFilter("API.apiId", Operator.EQ, "abc"); + org.hypertrace.core.query.service.api.Filter queryFilter = + QueryRequestUtil.createStringFilter( + "API.apiId", org.hypertrace.core.query.service.api.Operator.EQ, "abc"); getLeafOperatorMap() .forEach( (go, qo) -> filterMap.put( - Filter.newBuilder(gatewayFilterBuilder.build()).setOperator(go).build(), - org.hypertrace.core.query.service.api.Filter.newBuilder( - queryFilterBuilder.build()) - .setOperator(qo) - .build())); + gatewayFilter.toBuilder().setOperator(go).build(), + queryFilter.toBuilder().setOperator(qo).build())); // Construct boolean filters too filterMap.put( @@ -179,16 +159,9 @@ private Map getLeafOpe private Map getFunctionMap() { Expression gatewayExprArgument = - Expression.newBuilder() - .setColumnIdentifier(ColumnIdentifier.newBuilder().setColumnName("API.apiId").build()) - .build(); + QueryExpressionUtil.buildAttributeExpression("API.apiId").build(); org.hypertrace.core.query.service.api.Expression queryExprArgument = - org.hypertrace.core.query.service.api.Expression.newBuilder() - .setColumnIdentifier( - org.hypertrace.core.query.service.api.ColumnIdentifier.newBuilder() - .setColumnName("API.apiId") - .build()) - .build(); + QueryRequestUtil.createAttributeExpression("API.apiId"); return Map.of( FunctionExpression.newBuilder() .setFunction(FunctionType.SUM) diff --git a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/converter/QueryAndGatewayDtoConverterTest.java b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/converter/QueryAndGatewayDtoConverterTest.java index 24f60b71..7dd767c9 100644 --- a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/converter/QueryAndGatewayDtoConverterTest.java +++ b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/converter/QueryAndGatewayDtoConverterTest.java @@ -9,12 +9,8 @@ import java.util.List; import org.hypertrace.core.query.service.api.Filter; -import org.hypertrace.gateway.service.v1.common.ColumnIdentifier; -import org.hypertrace.gateway.service.v1.common.Expression; -import org.hypertrace.gateway.service.v1.common.LiteralConstant; +import org.hypertrace.gateway.service.common.util.QueryExpressionUtil; import org.hypertrace.gateway.service.v1.common.Operator; -import org.hypertrace.gateway.service.v1.common.Value; -import org.hypertrace.gateway.service.v1.common.ValueType; import org.junit.jupiter.api.Test; class QueryAndGatewayDtoConverterTest { @@ -79,17 +75,11 @@ org.hypertrace.gateway.service.v1.common.Filter buildGatewayTimerangeFilter( } org.hypertrace.gateway.service.v1.common.Filter buildLongFilter( - String col, Operator operator, long value) { + String attributeId, Operator operator, long value) { return org.hypertrace.gateway.service.v1.common.Filter.newBuilder() - .setLhs( - Expression.newBuilder() - .setColumnIdentifier(ColumnIdentifier.newBuilder().setColumnName(col).build())) + .setLhs(QueryExpressionUtil.buildAttributeExpression(attributeId)) .setOperator(operator) - .setRhs( - Expression.newBuilder() - .setLiteral( - LiteralConstant.newBuilder() - .setValue(Value.newBuilder().setValueType(ValueType.LONG).setLong(value)))) + .setRhs(QueryExpressionUtil.getLiteralExpression(value)) .build(); } } diff --git a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/datafetcher/EntityInteractionsFetcherTest.java b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/datafetcher/EntityInteractionsFetcherTest.java index 823eb7d2..c9a82fc7 100644 --- a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/datafetcher/EntityInteractionsFetcherTest.java +++ b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/datafetcher/EntityInteractionsFetcherTest.java @@ -2,7 +2,11 @@ import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createBetweenTimesFilter; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createFilter; +import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createStringArrayLiteralExpression; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createStringNullLiteralExpression; +import static org.hypertrace.gateway.service.common.util.QueryExpressionUtil.buildAttributeExpression; +import static org.hypertrace.gateway.service.common.util.QueryExpressionUtil.buildStringFilter; +import static org.hypertrace.gateway.service.common.util.QueryExpressionUtil.getAggregateFunctionExpression; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.fail; @@ -33,9 +37,7 @@ import org.hypertrace.gateway.service.v1.common.ColumnIdentifier; import org.hypertrace.gateway.service.v1.common.DomainEntityType; import org.hypertrace.gateway.service.v1.common.Expression; -import org.hypertrace.gateway.service.v1.common.Expression.Builder; import org.hypertrace.gateway.service.v1.common.Filter; -import org.hypertrace.gateway.service.v1.common.FunctionExpression; import org.hypertrace.gateway.service.v1.common.FunctionType; import org.hypertrace.gateway.service.v1.common.LiteralConstant; import org.hypertrace.gateway.service.v1.common.Operator; @@ -51,7 +53,7 @@ public class EntityInteractionsFetcherTest extends AbstractGatewayServiceTest { private final InteractionsRequest fromServiceInteractions = InteractionsRequest.newBuilder() - .setFilter(getSimpleFilter("INTERACTION.fromEntityType", "SERVICE")) + .setFilter(buildStringFilter("INTERACTION.fromEntityType", Operator.EQ, "SERVICE")) .addSelection( getAggregateFunctionExpression( "INTERACTION.bytesReceived", FunctionType.SUM, "SUM_bytes_received")) @@ -59,12 +61,12 @@ public class EntityInteractionsFetcherTest extends AbstractGatewayServiceTest { private final InteractionsRequest toServiceInteractions = InteractionsRequest.newBuilder() - .setFilter(getSimpleFilter("INTERACTION.toEntityType", "SERVICE")) + .setFilter(buildStringFilter("INTERACTION.toEntityType", Operator.EQ, "SERVICE")) .addSelection( getAggregateFunctionExpression( "INTERACTION.bytesSent", FunctionType.SUM, "SUM_bytes_sent")) .addSelection( - QueryExpressionUtil.getAggregateFunctionExpression( + getAggregateFunctionExpression( "INTERACTION.bytesSent", FunctionType.AVGRATE, "AVGRATE_bytes_sent_60", @@ -73,7 +75,7 @@ public class EntityInteractionsFetcherTest extends AbstractGatewayServiceTest { .build()), false)) .addSelection( - QueryExpressionUtil.getAggregateFunctionExpression( + getAggregateFunctionExpression( "INTERACTION.bytesSent", FunctionType.PERCENTILE, "p99_bytes_sent", @@ -84,7 +86,7 @@ public class EntityInteractionsFetcherTest extends AbstractGatewayServiceTest { private final InteractionsRequest toApiInteractions = InteractionsRequest.newBuilder() - .setFilter(getSimpleFilter("Interaction.attributes.to_entity_type", "API")) + .setFilter(buildStringFilter("Interaction.attributes.to_entity_type", Operator.EQ, "API")) .addSelection( getAggregateFunctionExpression( "Interaction.metrics.bytes_sent", FunctionType.SUM, "SUM_bytes_sent")) @@ -92,35 +94,6 @@ public class EntityInteractionsFetcherTest extends AbstractGatewayServiceTest { @Mock private AttributeMetadataProvider attributeMetadataProvider; - private Builder getColumnExpression(String columnName) { - return Expression.newBuilder() - .setColumnIdentifier(ColumnIdentifier.newBuilder().setColumnName(columnName)); - } - - private Expression.Builder getLiteralExpression(String value) { - return Expression.newBuilder() - .setLiteral( - LiteralConstant.newBuilder() - .setValue(Value.newBuilder().setString(value).setValueType(ValueType.STRING))); - } - - private Expression.Builder getAggregateFunctionExpression( - String columnName, FunctionType function, String alias) { - return Expression.newBuilder() - .setFunction( - FunctionExpression.newBuilder() - .setFunction(function) - .setAlias(alias) - .addArguments(getColumnExpression(columnName))); - } - - private Filter.Builder getSimpleFilter(String columnName, String value) { - return Filter.newBuilder() - .setLhs(getColumnExpression(columnName)) - .setOperator(Operator.EQ) - .setRhs(getLiteralExpression(value)); - } - @Test public void testServiceToServiceEdgeQueryRequests() { EntitiesRequest request = @@ -128,7 +101,7 @@ public void testServiceToServiceEdgeQueryRequests() { .setEntityType(DomainEntityType.SERVICE.name()) .setStartTimeMillis(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30)) .setEndTimeMillis(System.currentTimeMillis()) - .addSelection(getColumnExpression("SERVICE.name")) + .addSelection(buildAttributeExpression("SERVICE.name")) .setIncomingInteractions(fromServiceInteractions) .setOutgoingInteractions(toServiceInteractions) .build(); @@ -183,10 +156,7 @@ public void testFromMultipleEntitiesQuery() { Filter.Builder entityTypeFilter = Filter.newBuilder() - .setLhs( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder().setColumnName("INTERACTION.fromEntityType"))) + .setLhs(buildAttributeExpression("INTERACTION.fromEntityType")) .setOperator(Operator.IN) .setRhs( Expression.newBuilder() @@ -198,10 +168,7 @@ public void testFromMultipleEntitiesQuery() { .addAllStringArray(entityTypes)))); Filter.Builder entityIdFilter = Filter.newBuilder() - .setLhs( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder().setColumnName("INTERACTION.fromEntityId"))) + .setLhs(buildAttributeExpression("INTERACTION.fromEntityId")) .setOperator(Operator.IN) .setRhs( Expression.newBuilder() @@ -219,10 +186,10 @@ public void testFromMultipleEntitiesQuery() { .addChildFilter(entityTypeFilter) .addChildFilter(entityIdFilter)) .addSelection( - QueryExpressionUtil.getAggregateFunctionExpression( + getAggregateFunctionExpression( "INTERACTION.bytesReceived", FunctionType.SUM, "SUM_bytes_received")) .addSelection( - QueryExpressionUtil.getAggregateFunctionExpression( + getAggregateFunctionExpression( "INTERACTION.bytesReceived", FunctionType.AVGRATE, "AVGRATE_bytes_received_60", @@ -231,7 +198,7 @@ public void testFromMultipleEntitiesQuery() { .build()), false)) .addSelection( - QueryExpressionUtil.getAggregateFunctionExpression( + getAggregateFunctionExpression( "INTERACTION.bytesReceived", FunctionType.PERCENTILE, "p99_bytes_received", @@ -244,7 +211,7 @@ public void testFromMultipleEntitiesQuery() { .setEntityType(DomainEntityType.SERVICE.name()) .setStartTimeMillis(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30)) .setEndTimeMillis(System.currentTimeMillis()) - .addSelection(getColumnExpression("SERVICE.name")) + .addSelection(buildAttributeExpression("SERVICE.name")) .setIncomingInteractions(fromInteraction) .build(); @@ -283,10 +250,7 @@ public void testToMultipleEntityTypesQuery() { Filter.Builder entityTypeFilter = Filter.newBuilder() - .setLhs( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder().setColumnName("INTERACTION.toEntityType"))) + .setLhs(buildAttributeExpression("INTERACTION.toEntityType")) .setOperator(Operator.IN) .setRhs( Expression.newBuilder() @@ -308,9 +272,9 @@ public void testToMultipleEntityTypesQuery() { .setEntityType(DomainEntityType.SERVICE.name()) .setStartTimeMillis(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30)) .setEndTimeMillis(System.currentTimeMillis()) - .addSelection(getColumnExpression("SERVICE.name")) - .addSelection(getColumnExpression("INTERACTION.fromEntityType")) - .addSelection(getColumnExpression("INTERACTION.toEntityType")) + .addSelection(buildAttributeExpression("SERVICE.name")) + .addSelection(buildAttributeExpression("INTERACTION.fromEntityType")) + .addSelection(buildAttributeExpression("INTERACTION.toEntityType")) .setOutgoingInteractions(toInteraction) .build(); @@ -501,25 +465,11 @@ public void testEntityWithInteractionMappingToMultipleAttributes() { private org.hypertrace.core.query.service.api.Filter createStringArrayFilter( org.hypertrace.core.query.service.api.Operator operator, - String columnName, + String attributeId, List valueList) { - return org.hypertrace.core.query.service.api.Filter.newBuilder() - .setOperator(operator) - .setLhs( - org.hypertrace.core.query.service.api.Expression.newBuilder() - .setColumnIdentifier( - org.hypertrace.core.query.service.api.ColumnIdentifier.newBuilder() - .setColumnName(columnName))) - .setRhs( - org.hypertrace.core.query.service.api.Expression.newBuilder() - .setLiteral( - org.hypertrace.core.query.service.api.LiteralConstant.newBuilder() - .setValue( - org.hypertrace.core.query.service.api.Value.newBuilder() - .addAllStringArray(valueList) - .setValueType( - org.hypertrace.core.query.service.api.ValueType.STRING_ARRAY)))) - .build(); + + return org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createFilter( + attributeId, operator, createStringArrayLiteralExpression(valueList)); } private EntitiesRequest.Builder getValidServiceEntitiesRequest() { @@ -527,7 +477,7 @@ private EntitiesRequest.Builder getValidServiceEntitiesRequest() { .setEntityType(DomainEntityType.SERVICE.name()) .setStartTimeMillis(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30)) .setEndTimeMillis(System.currentTimeMillis()) - .addSelection(getColumnExpression("Service.name")); + .addSelection(buildAttributeExpression("Service.name")); } private EntitiesRequest.Builder getValidBackendEntitiesRequest() { @@ -535,7 +485,7 @@ private EntitiesRequest.Builder getValidBackendEntitiesRequest() { .setEntityType(DomainEntityType.BACKEND.name()) .setStartTimeMillis(System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30)) .setEndTimeMillis(System.currentTimeMillis()) - .addSelection(getColumnExpression("Backend.name")); + .addSelection(buildAttributeExpression("Backend.name")); } @Test @@ -543,7 +493,7 @@ public void testCornerCases() { // No selections InteractionsRequest interactionsRequest = InteractionsRequest.newBuilder() - .setFilter(getSimpleFilter("INTERACTION.fromEntityType", "SERVICE")) + .setFilter(buildStringFilter("INTERACTION.fromEntityType", Operator.EQ, "SERVICE")) .build(); EntitiesRequest request = @@ -588,13 +538,13 @@ private Collection getInvalidRequests() { getValidServiceEntitiesRequest() .setIncomingInteractions( // No filter but selections available. - InteractionsRequest.newBuilder().addSelection(getColumnExpression("test"))) + InteractionsRequest.newBuilder().addSelection(buildAttributeExpression("test"))) .build(), getValidServiceEntitiesRequest() .setOutgoingInteractions( // No filter but filter available InteractionsRequest.newBuilder() - .setFilter(getSimpleFilter("test", "value")) + .setFilter(QueryExpressionUtil.buildStringFilter("test", Operator.EQ, "value")) .build()) .build(), // Backend to service interactions diff --git a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/datafetcher/QueryServiceEntityFetcherTests.java b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/datafetcher/QueryServiceEntityFetcherTests.java index fcdac299..f56d40a8 100644 --- a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/datafetcher/QueryServiceEntityFetcherTests.java +++ b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/datafetcher/QueryServiceEntityFetcherTests.java @@ -11,7 +11,7 @@ import static org.hypertrace.gateway.service.common.QueryServiceRequestAndResponseUtils.createQsAggregationExpression; import static org.hypertrace.gateway.service.common.QueryServiceRequestAndResponseUtils.createQsRequestFilter; import static org.hypertrace.gateway.service.common.QueryServiceRequestAndResponseUtils.getResultSetChunk; -import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createColumnExpression; +import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createAttributeExpression; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createStringFilter; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createTimeColumnGroupByExpression; import static org.hypertrace.gateway.service.v1.common.Operator.AND; @@ -160,7 +160,7 @@ public void testGetTimeAggregatedMetrics() { createStringFilter(API_DISCOVERY_STATE_ATTR, Operator.EQ, "DISCOVERED"))) .addAllGroupBy( List.of(API_ID_ATTR).stream() - .map(QueryRequestUtil::createColumnExpression) + .map(QueryRequestUtil::createAttributeExpression) .collect(Collectors.toList())) .addGroupBy(createTimeColumnGroupByExpression(API_START_TIME_ATTR, 30)) .setOffset(0) @@ -316,7 +316,7 @@ public void testGetTimeAggregatedMetricsForAvgRateInIsoFormat() { createStringFilter(API_DISCOVERY_STATE_ATTR, Operator.EQ, "DISCOVERED"))) .addAllGroupBy( List.of(API_ID_ATTR).stream() - .map(QueryRequestUtil::createColumnExpression) + .map(QueryRequestUtil::createAttributeExpression) .collect(Collectors.toList())) .addGroupBy(createTimeColumnGroupByExpression(API_START_TIME_ATTR, 30)) .setOffset(0) @@ -422,9 +422,9 @@ public void testGetEntities() { QueryRequest expectedQueryRequest = QueryRequest.newBuilder() - .addSelection(createColumnExpression(API_ID_ATTR)) + .addSelection(createAttributeExpression(API_ID_ATTR)) .addSelection(createQsAggregationExpression("SUM", API_NUM_CALLS_ATTR, "Sum_numCalls")) - .addSelection(createColumnExpression(API_NAME_ATTR)) + .addSelection(createAttributeExpression(API_NAME_ATTR)) .setFilter( createQsRequestFilter( API_START_TIME_ATTR, @@ -432,8 +432,8 @@ public void testGetEntities() { startTime, endTime, createStringFilter(API_DISCOVERY_STATE_ATTR, Operator.EQ, "DISCOVERED"))) - .addGroupBy(createColumnExpression(API_ID_ATTR)) - .addGroupBy(createColumnExpression(API_NAME_ATTR)) + .addGroupBy(createAttributeExpression(API_ID_ATTR)) + .addGroupBy(createAttributeExpression(API_NAME_ATTR)) .setOffset(offset) .setLimit(QueryServiceClient.DEFAULT_QUERY_SERVICE_GROUP_BY_LIMIT) .addAllOrderBy( @@ -509,7 +509,7 @@ public void test_getEntitiesWithPagination() { QueryRequest expectedQueryRequest = QueryRequest.newBuilder() - .addSelection(createColumnExpression(API_ID_ATTR)) + .addSelection(createAttributeExpression(API_ID_ATTR)) .addSelection(createQsAggregationExpression("COUNT", API_ID_ATTR)) .setFilter( createQsRequestFilter( @@ -518,7 +518,7 @@ public void test_getEntitiesWithPagination() { startTime, endTime, createStringFilter(API_DISCOVERY_STATE_ATTR, Operator.EQ, "DISCOVERED"))) - .addGroupBy(createColumnExpression(API_ID_ATTR)) + .addGroupBy(createAttributeExpression(API_ID_ATTR)) .setOffset(offset) .setLimit(limit) .addAllOrderBy( @@ -570,7 +570,7 @@ public void test_getEntitiesWithoutPagination() { QueryRequest expectedQueryRequest = QueryRequest.newBuilder() - .addSelection(createColumnExpression(API_ID_ATTR)) + .addSelection(createAttributeExpression(API_ID_ATTR)) .addSelection(createQsAggregationExpression("COUNT", API_ID_ATTR)) .setFilter( createQsRequestFilter( @@ -579,7 +579,7 @@ public void test_getEntitiesWithoutPagination() { startTime, endTime, createStringFilter(API_DISCOVERY_STATE_ATTR, Operator.EQ, "DISCOVERED"))) - .addGroupBy(createColumnExpression(API_ID_ATTR)) + .addGroupBy(createAttributeExpression(API_ID_ATTR)) .setLimit(QueryServiceClient.DEFAULT_QUERY_SERVICE_GROUP_BY_LIMIT) .addAllOrderBy( QueryAndGatewayDtoConverter.convertToQueryOrderByExpressions(orderByExpressions)) @@ -621,8 +621,8 @@ public void test_getEntitiesBySpace() { QueryRequest expectedQueryRequest = QueryRequest.newBuilder() - .addSelection(createColumnExpression(API_ID_ATTR)) - .addSelection(createColumnExpression(API_NAME_ATTR)) + .addSelection(createAttributeExpression(API_ID_ATTR)) + .addSelection(createAttributeExpression(API_NAME_ATTR)) .addSelection(QueryRequestUtil.createCountByColumnSelection("API.id")) .setFilter( createQsRequestFilter( @@ -631,8 +631,8 @@ public void test_getEntitiesBySpace() { startTime, endTime, createStringFilter(SPACE_IDS_ATTR, Operator.EQ, "test-space"))) - .addGroupBy(createColumnExpression(API_ID_ATTR)) - .addGroupBy(createColumnExpression(API_NAME_ATTR)) + .addGroupBy(createAttributeExpression(API_ID_ATTR)) + .addGroupBy(createAttributeExpression(API_NAME_ATTR)) .setOffset(offset) .setLimit(QueryServiceClient.DEFAULT_QUERY_SERVICE_GROUP_BY_LIMIT) .build(); diff --git a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/transformer/RequestPreProcessorTest.java b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/transformer/RequestPreProcessorTest.java index 5090936d..bdf2a3c0 100644 --- a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/transformer/RequestPreProcessorTest.java +++ b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/transformer/RequestPreProcessorTest.java @@ -15,7 +15,6 @@ import org.hypertrace.gateway.service.common.config.ScopeFilterConfigs; import org.hypertrace.gateway.service.common.util.QueryExpressionUtil; import org.hypertrace.gateway.service.entity.EntitiesRequestContext; -import org.hypertrace.gateway.service.testutils.GatewayExpressionCreator; import org.hypertrace.gateway.service.v1.common.Filter; import org.hypertrace.gateway.service.v1.common.FunctionType; import org.hypertrace.gateway.service.v1.common.Operator; @@ -59,16 +58,12 @@ public void setup() { .setEntityType("SERVICE") .setStartTimeMillis(startTime) .setEndTimeMillis(endTime) - .setFilter( - GatewayExpressionCreator.createFilter( - QueryExpressionUtil.getColumnExpression("SERVICE.name"), - Operator.LIKE, - QueryExpressionUtil.getLiteralExpression("log"))) - .addSelection(QueryExpressionUtil.getColumnExpression("SERVICE.id")) + .setFilter(QueryExpressionUtil.buildStringFilter("SERVICE.name", Operator.LIKE, "log")) + .addSelection(QueryExpressionUtil.buildAttributeExpression("SERVICE.id")) .addSelection( - QueryExpressionUtil.getColumnExpression( + QueryExpressionUtil.buildAttributeExpression( "SERVICE.id")) // Duplicate should be removed by the processor - .addSelection(QueryExpressionUtil.getColumnExpression("SERVICE.name")) + .addSelection(QueryExpressionUtil.buildAttributeExpression("SERVICE.name")) .addSelection( QueryExpressionUtil.getAggregateFunctionExpression( "SERVICE.duration", FunctionType.AVG, "AVG#SERVICE|duration")) @@ -81,7 +76,7 @@ public void setup() { .build(); EntitiesRequest transformedRequest = - requestPreProcessor.transformFilter(entitiesRequest, entitiesRequestContext); + requestPreProcessor.process(entitiesRequest, entitiesRequestContext); // RequestPreProcessor should remove duplicate Service.Id selection and add scope filters // config. @@ -94,25 +89,18 @@ public void setup() { Filter.newBuilder() .setOperator(Operator.AND) .addChildFilter( - GatewayExpressionCreator.createFilter( - QueryExpressionUtil.getColumnExpression("SERVICE.name"), - Operator.LIKE, - QueryExpressionUtil.getLiteralExpression("log"))) + QueryExpressionUtil.buildStringFilter("SERVICE.name", Operator.LIKE, "log")) .addChildFilter( Filter.newBuilder() .setOperator(Operator.AND) .addChildFilter( - GatewayExpressionCreator.createFilter( - QueryExpressionUtil.getColumnExpression("SERVICE.id"), - Operator.NEQ, - QueryExpressionUtil.getLiteralExpression("null"))) + QueryExpressionUtil.buildStringFilter( + "SERVICE.id", Operator.NEQ, "null")) .addChildFilter( - GatewayExpressionCreator.createFilter( - QueryExpressionUtil.getColumnExpression("SERVICE.name"), - Operator.NEQ, - QueryExpressionUtil.getLiteralExpression("foo"))))) - .addSelection(QueryExpressionUtil.getColumnExpression("SERVICE.id")) - .addSelection(QueryExpressionUtil.getColumnExpression("SERVICE.name")) + QueryExpressionUtil.buildStringFilter( + "SERVICE.name", Operator.NEQ, "foo")))) + .addSelection(QueryExpressionUtil.buildAttributeExpression("SERVICE.id")) + .addSelection(QueryExpressionUtil.buildAttributeExpression("SERVICE.name")) .addSelection( QueryExpressionUtil.getAggregateFunctionExpression( "SERVICE.duration", FunctionType.AVG, "AVG#SERVICE|duration")) @@ -140,16 +128,13 @@ public void testApiTracesRequestScopeFilterConfigsAdded() { .setEndTimeMillis(endTime) .setScope("API_TRACE") .setFilter( - GatewayExpressionCreator.createFilter( - QueryExpressionUtil.getColumnExpression("API_TRACE.serviceName"), - Operator.LIKE, - QueryExpressionUtil.getLiteralExpression("log"))) - .addSelection(QueryExpressionUtil.getColumnExpression("API_TRACE.id")) - .addSelection(QueryExpressionUtil.getColumnExpression("API_TRACE.serviceName")) + QueryExpressionUtil.buildStringFilter( + "API_TRACE.serviceName", Operator.LIKE, "log")) + .addSelection(QueryExpressionUtil.buildAttributeExpression("API_TRACE.id")) + .addSelection(QueryExpressionUtil.buildAttributeExpression("API_TRACE.serviceName")) .build(); - TracesRequest transformedRequest = - requestPreProcessor.transformFilter(tracesRequest, requestContext); + TracesRequest transformedRequest = requestPreProcessor.process(tracesRequest, requestContext); // RequestPreProcessor should add scope filters config. Assertions.assertEquals( @@ -161,26 +146,19 @@ public void testApiTracesRequestScopeFilterConfigsAdded() { Filter.newBuilder() .setOperator(Operator.AND) .addChildFilter( - GatewayExpressionCreator.createFilter( - QueryExpressionUtil.getColumnExpression("API_TRACE.serviceName"), - Operator.LIKE, - QueryExpressionUtil.getLiteralExpression("log"))) + QueryExpressionUtil.buildStringFilter( + "API_TRACE.serviceName", Operator.LIKE, "log")) .addChildFilter( Filter.newBuilder() .setOperator(Operator.AND) .addChildFilter( - GatewayExpressionCreator.createFilter( - QueryExpressionUtil.getColumnExpression( - "API_TRACE.apiBoundaryType"), - Operator.EQ, - QueryExpressionUtil.getLiteralExpression("ENTRY"))) + QueryExpressionUtil.buildStringFilter( + "API_TRACE.apiBoundaryType", Operator.EQ, "ENTRY")) .addChildFilter( - GatewayExpressionCreator.createFilter( - QueryExpressionUtil.getColumnExpression("API_TRACE.apiId"), - Operator.NEQ, - QueryExpressionUtil.getLiteralExpression("null"))))) - .addSelection(QueryExpressionUtil.getColumnExpression("API_TRACE.id")) - .addSelection(QueryExpressionUtil.getColumnExpression("API_TRACE.serviceName")) + QueryExpressionUtil.buildStringFilter( + "API_TRACE.apiId", Operator.NEQ, "null")))) + .addSelection(QueryExpressionUtil.buildAttributeExpression("API_TRACE.id")) + .addSelection(QueryExpressionUtil.buildAttributeExpression("API_TRACE.serviceName")) .build(), transformedRequest); } diff --git a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/util/MetricAggregationFunctionUtilTest.java b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/util/MetricAggregationFunctionUtilTest.java index 63f3db1a..605ff1d2 100644 --- a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/util/MetricAggregationFunctionUtilTest.java +++ b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/util/MetricAggregationFunctionUtilTest.java @@ -107,7 +107,7 @@ private void createFunctionAndVerifyKind( QueryExpressionUtil.getAggregateFunctionExpression(metricName, functionType, alias, true) .build(); Map aliasToKind = - MetricAggregationFunctionUtil.getValueTypeFromFunction( + MetricAggregationFunctionUtil.getValueTypeForFunctionType( Collections.singletonMap(alias, expr.getFunction()), attributeMetadataMap); Assertions.assertEquals(expectedKind, aliasToKind.get(alias)); } diff --git a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/util/QueryExpressionUtilTest.java b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/util/QueryExpressionUtilTest.java index db41e9f6..ac1e4fe3 100644 --- a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/util/QueryExpressionUtilTest.java +++ b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/common/util/QueryExpressionUtilTest.java @@ -31,7 +31,7 @@ public void testAlignTimeToPeriod() { public void testBooleanFilter() { Filter booleanFilter = QueryExpressionUtil.getBooleanFilter("API.is_external", true).build(); Assertions.assertEquals( - "API.is_external", booleanFilter.getLhs().getColumnIdentifier().getColumnName()); + "API.is_external", booleanFilter.getLhs().getAttributeExpression().getAttributeId()); Assertions.assertEquals(Operator.EQ, booleanFilter.getOperator()); Assertions.assertTrue(booleanFilter.getRhs().getLiteral().getValue().getBoolean()); } diff --git a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/entity/EntitiesRequestResponseProcessorTest.java b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/entity/EntitiesRequestResponseProcessorTest.java index 05116273..d128971c 100644 --- a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/entity/EntitiesRequestResponseProcessorTest.java +++ b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/entity/EntitiesRequestResponseProcessorTest.java @@ -19,6 +19,7 @@ import org.hypertrace.gateway.service.common.util.QueryExpressionUtil; import org.hypertrace.gateway.service.v1.common.Expression; import org.hypertrace.gateway.service.v1.common.FunctionType; +import org.hypertrace.gateway.service.v1.common.Operator; import org.hypertrace.gateway.service.v1.common.SortOrder; import org.hypertrace.gateway.service.v1.entity.EntitiesRequest; import org.junit.jupiter.api.Assertions; @@ -32,11 +33,11 @@ public class EntitiesRequestResponseProcessorTest { private final EntitiesRequest originalRequest = EntitiesRequest.newBuilder() .setEntityType("API") - .addSelection(QueryExpressionUtil.getColumnExpression("API.duplicate")) - .addSelection(QueryExpressionUtil.getColumnExpression("API.duplicate")) - .addSelection(QueryExpressionUtil.getColumnExpression("API.apiId")) - .addSelection(QueryExpressionUtil.getColumnExpression("API.apiName")) - .setFilter(QueryExpressionUtil.getSimpleFilter("API.apiId", "name1")) + .addSelection(QueryExpressionUtil.buildAttributeExpression("API.duplicate")) + .addSelection(QueryExpressionUtil.buildAttributeExpression("API.duplicate")) + .addSelection(QueryExpressionUtil.buildAttributeExpression("API.apiId")) + .addSelection(QueryExpressionUtil.buildAttributeExpression("API.apiName")) + .setFilter(QueryExpressionUtil.buildStringFilter("API.apiId", Operator.EQ, "name1")) .addOrderBy(QueryExpressionUtil.getOrderBy("API.apiId", SortOrder.ASC)) .build(); @Mock private AttributeMetadataProvider attributeMetadataProvider; @@ -55,10 +56,10 @@ public void testUniqueColumnsTransform() { EntitiesRequest originalRequest = EntitiesRequest.newBuilder() .setEntityType("API") - .addSelection(QueryExpressionUtil.getColumnExpression("API.duplicate")) - .addSelection(QueryExpressionUtil.getColumnExpression("API.duplicate")) - .addSelection(QueryExpressionUtil.getColumnExpression("API.duplicate")) - .addSelection(QueryExpressionUtil.getColumnExpression("API.apiName")) + .addSelection(QueryExpressionUtil.buildAttributeExpression("API.duplicate")) + .addSelection(QueryExpressionUtil.buildAttributeExpression("API.duplicate")) + .addSelection(QueryExpressionUtil.buildAttributeExpression("API.duplicate")) + .addSelection(QueryExpressionUtil.buildAttributeExpression("API.apiName")) .addSelection( QueryExpressionUtil.getAggregateFunctionExpression( "API.metrics.bytes_received", FunctionType.SUM, "SUM_bytes_received", true)) @@ -66,8 +67,7 @@ public void testUniqueColumnsTransform() { EntitiesRequestContext context = mock(EntitiesRequestContext.class); when(context.getTimestampAttributeId()).thenReturn("API.startTime"); - EntitiesRequest transformedRequest = - requestPreProcessor.transformFilter(originalRequest, context); + EntitiesRequest transformedRequest = requestPreProcessor.process(originalRequest, context); List expressionList = transformedRequest.getSelectionList(); Assertions.assertEquals(3, expressionList.size()); } diff --git a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/entity/EntityServiceTest.java b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/entity/EntityServiceTest.java index 90e1703b..0ab189d8 100644 --- a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/entity/EntityServiceTest.java +++ b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/entity/EntityServiceTest.java @@ -6,13 +6,16 @@ import static org.hypertrace.gateway.service.common.QueryServiceRequestAndResponseUtils.createQsAggregationExpression; import static org.hypertrace.gateway.service.common.QueryServiceRequestAndResponseUtils.createQsDefaultRequestFilter; import static org.hypertrace.gateway.service.common.QueryServiceRequestAndResponseUtils.getResultSetChunk; +import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createAttributeExpression; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createBetweenTimesFilter; -import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createColumnExpression; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createCompositeFilter; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createFilter; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createStringArrayLiteralExpression; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createStringNullLiteralExpression; import static org.hypertrace.gateway.service.common.converters.QueryRequestUtil.createTimeColumnGroupByExpression; +import static org.hypertrace.gateway.service.common.util.QueryExpressionUtil.alignToPeriodBoundary; +import static org.hypertrace.gateway.service.common.util.QueryExpressionUtil.buildAttributeExpression; +import static org.hypertrace.gateway.service.common.util.QueryExpressionUtil.getAggregateFunctionExpression; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.when; @@ -43,12 +46,9 @@ import org.hypertrace.gateway.service.common.QueryServiceRequestAndResponseUtils; import org.hypertrace.gateway.service.common.RequestContext; import org.hypertrace.gateway.service.common.config.ScopeFilterConfigs; -import org.hypertrace.gateway.service.common.util.QueryExpressionUtil; import org.hypertrace.gateway.service.entity.config.EntityIdColumnsConfigs; import org.hypertrace.gateway.service.entity.config.LogConfig; -import org.hypertrace.gateway.service.v1.common.ColumnIdentifier; import org.hypertrace.gateway.service.v1.common.Expression; -import org.hypertrace.gateway.service.v1.common.FunctionExpression; import org.hypertrace.gateway.service.v1.common.FunctionType; import org.hypertrace.gateway.service.v1.common.LiteralConstant; import org.hypertrace.gateway.service.v1.common.Operator; @@ -203,8 +203,8 @@ public void testGetEntitiesOnlySelectFromSingleSourceWithTimeRangeShouldUseQuery .setEntityType("API") .setStartTimeMillis(startTime) .setEndTimeMillis(endTime) - .addSelection(getExpressionFor("API.apiId", "API Id")) - .addSelection(getExpressionFor("API.apiName", "API Name")) + .addSelection(buildAttributeExpression("API.apiId", "API Id")) + .addSelection(buildAttributeExpression("API.apiName", "API Name")) .setLimit(2) .build(); @@ -216,10 +216,10 @@ public void testGetEntitiesOnlySelectFromSingleSourceWithTimeRangeShouldUseQuery QueryRequest expectedQueryRequest = QueryRequest.newBuilder() .addSelection( - createColumnExpression( + createAttributeExpression( "API.apiId")) // Added implicitly in the getEntitiesAndAggregatedMetrics() in // order to do GroupBy on the entity id - .addSelection(createColumnExpression("API.apiName", "API Name")) + .addSelection(createAttributeExpression("API.apiName", "API Name")) // QueryServiceEntityFetcher adds Count(entityId) to the request for one that does not // have an aggregation. // This is because internally a GroupBy request is created out of the entities request @@ -227,8 +227,8 @@ public void testGetEntitiesOnlySelectFromSingleSourceWithTimeRangeShouldUseQuery // an aggregation is needed. .addSelection(createQsAggregationExpression("COUNT", "API.apiId")) .setFilter(queryServiceFilter) - .addGroupBy(createColumnExpression("API.apiId")) - .addGroupBy(createColumnExpression("API.apiName", "API Name")) + .addGroupBy(createAttributeExpression("API.apiId")) + .addGroupBy(createAttributeExpression("API.apiName", "API Name")) .setLimit(QueryServiceClient.DEFAULT_QUERY_SERVICE_GROUP_BY_LIMIT) .build(); when(queryServiceClient.executeQuery(eq(expectedQueryRequest), any(), Mockito.anyInt())) @@ -248,7 +248,7 @@ public void testGetEntitiesOnlySelectFromSingleSourceWithTimeRangeShouldUseQuery expectedQueryRequest = QueryRequest.newBuilder() .addSelection( - createColumnExpression( + createAttributeExpression( "API.apiId")) // Added implicitly in the getEntitiesAndAggregatedMetrics() in // order to do GroupBy on the entity id // QueryServiceEntityFetcher adds Count(entityId) to the request for one that does not @@ -258,7 +258,7 @@ public void testGetEntitiesOnlySelectFromSingleSourceWithTimeRangeShouldUseQuery // an aggregation is needed. .addSelection(createQsAggregationExpression("COUNT", "API.apiId")) .setFilter(queryServiceFilter) - .addGroupBy(createColumnExpression("API.apiId")) + .addGroupBy(createAttributeExpression("API.apiId")) .setLimit(QueryServiceClient.DEFAULT_QUERY_SERVICE_GROUP_BY_LIMIT) .build(); @@ -298,7 +298,7 @@ public void testGetEntitiesOnlySelectFromMultipleSources() { org.hypertrace.entity.query.service.v1.ResultSetChunk.newBuilder() .setResultSetMetadata( generateEntityServiceResultSetMetadataFor( - "API.apiId", "API.httpMethod")) + "API.apiId", "API Http method")) .addRow(generateEntityServiceRowFor("apiId1", "GET")) .addRow(generateEntityServiceRowFor("apiId2", "POST")) .build()) @@ -321,15 +321,17 @@ public void testGetEntitiesOnlySelectFromMultipleSources() { .setFilter( org.hypertrace.gateway.service.v1.common.Filter.newBuilder() .setOperator(Operator.IN) - .setLhs(getExpressionFor("API.httpMethod", "API Http method")) + .setLhs(buildAttributeExpression("API.httpMethod", "API Http method")) .setRhs(getStringListLiteral(List.of("GET", "POST")))) - .addSelection(getExpressionFor("API.apiId", "API Id")) - .addSelection(getExpressionFor("API.apiName", "API Name")) - .addSelection(getExpressionFor("API.httpMethod", "API Http method")) - .addSelection(getFunctionExpressionFor(FunctionType.AVG, "API.duration", "duration")) + .addSelection(buildAttributeExpression("API.apiId", "API Id")) + .addSelection(buildAttributeExpression("API.apiName", "API Name")) + .addSelection(buildAttributeExpression("API.httpMethod", "API Http method")) + .addSelection( + getAggregateFunctionExpression("API.duration", FunctionType.AVG, "duration")) .addTimeAggregation( getTimeAggregationFor( - getFunctionExpressionFor(FunctionType.AVG, "API.duration", "duration_ts"))) + getAggregateFunctionExpression("API.duration", FunctionType.AVG, "duration_ts") + .build())) .build(); QueryRequest expectedQueryRequest = QueryRequest.newBuilder() @@ -339,21 +341,20 @@ public void testGetEntitiesOnlySelectFromMultipleSources() { "API.apiId", entitiesRequest.getStartTimeMillis(), entitiesRequest.getEndTimeMillis())) - .addSelection(createColumnExpression("API.apiId")) - .addSelection(createColumnExpression("API.apiName", "API Name")) + .addSelection(createAttributeExpression("API.apiId")) + .addSelection(createAttributeExpression("API.apiName", "API Name")) .addSelection( QueryServiceRequestAndResponseUtils.createQsAggregationExpression( "COUNT", "API.apiId")) - .addGroupBy(createColumnExpression("API.apiId")) - .addGroupBy(createColumnExpression("API.apiName", "API Name")) + .addGroupBy(createAttributeExpression("API.apiId")) + .addGroupBy(createAttributeExpression("API.apiName", "API Name")) .setLimit(10000) .build(); when(queryServiceClient.executeQuery(expectedQueryRequest, Map.of(), 500)) .thenReturn( List.of( ResultSetChunk.newBuilder() - .setResultSetMetadata( - generateResultSetMetadataFor("API.apiId", "API.apiName")) + .setResultSetMetadata(generateResultSetMetadataFor("API.apiId", "API Name")) .addRow(generateRowFor("apiId1", "/login")) .addRow(generateRowFor("apiId2", "/checkout")) .build()) @@ -371,13 +372,12 @@ public void testGetEntitiesOnlySelectFromMultipleSources() { entitiesRequest.getStartTimeMillis(), entitiesRequest.getEndTimeMillis()), createFilter( - createColumnExpression("API.apiId", "entityId0"), + createAttributeExpression("API.apiId", "entityId0"), IN, createStringArrayLiteralExpression(List.of("apiId2", "apiId1")))))) - .addSelection(createColumnExpression("API.apiId")) - .addSelection( - createQsAggregationExpression("AVG", "duration", "API.duration", "duration")) - .addGroupBy(createColumnExpression("API.apiId")) + .addSelection(createAttributeExpression("API.apiId")) + .addSelection(createQsAggregationExpression("AVG", "API.duration", "duration")) + .addGroupBy(createAttributeExpression("API.apiId")) .setLimit(10000) .build(); when(queryServiceClient.executeQuery(secondQueryRequest, Map.of(), 500)) @@ -390,10 +390,8 @@ public void testGetEntitiesOnlySelectFromMultipleSources() { .build()) .iterator()); - long alignedStartTime = - QueryExpressionUtil.alignToPeriodBoundary(entitiesRequest.getStartTimeMillis(), 60, true); - long alignedEndTime = - QueryExpressionUtil.alignToPeriodBoundary(entitiesRequest.getEndTimeMillis(), 60, false); + long alignedStartTime = alignToPeriodBoundary(entitiesRequest.getStartTimeMillis(), 60, true); + long alignedEndTime = alignToPeriodBoundary(entitiesRequest.getEndTimeMillis(), 60, false); QueryRequest thirdQueryRequest = QueryRequest.newBuilder() .setFilter( @@ -403,12 +401,11 @@ public void testGetEntitiesOnlySelectFromMultipleSources() { createFilter("API.apiId", NEQ, createStringNullLiteralExpression()), createBetweenTimesFilter("API.startTime", alignedStartTime, alignedEndTime), createFilter( - createColumnExpression("API.apiId", "entityId0"), + createAttributeExpression("API.apiId", "entityId0"), IN, createStringArrayLiteralExpression(List.of("apiId2", "apiId1")))))) - .addSelection( - createQsAggregationExpression("AVG", "duration_ts", "API.duration", "duration_ts")) - .addGroupBy(createColumnExpression("API.apiId")) + .addSelection(createQsAggregationExpression("AVG", "API.duration", "duration_ts")) + .addGroupBy(createAttributeExpression("API.apiId")) .addGroupBy(createTimeColumnGroupByExpression("API.startTime", 60)) .setLimit(10000) .build(); @@ -427,13 +424,13 @@ public void testGetEntitiesOnlySelectFromMultipleSources() { Assertions.assertNotNull(response); Assertions.assertEquals(2, response.getTotal()); for (Entity entity : response.getEntityList()) { - if ("apiId1".equals(entity.getAttributeMap().get("API.apiId").getString())) { - Assertions.assertEquals("/login", entity.getAttributeMap().get("API.apiName").getString()); - Assertions.assertEquals("GET", entity.getAttributeMap().get("API.httpMethod").getString()); - } else if ("apiId2".equals(entity.getAttributeMap().get("API.apiId").getString())) { + if ("apiId1".equals(entity.getAttributeMap().get("API Id").getString())) { + Assertions.assertEquals("/login", entity.getAttributeMap().get("API Name").getString()); + Assertions.assertEquals("GET", entity.getAttributeMap().get("API Http method").getString()); + } else if ("apiId2".equals(entity.getAttributeMap().get("API Id").getString())) { + Assertions.assertEquals("/checkout", entity.getAttributeMap().get("API Name").getString()); Assertions.assertEquals( - "/checkout", entity.getAttributeMap().get("API.apiName").getString()); - Assertions.assertEquals("POST", entity.getAttributeMap().get("API.httpMethod").getString()); + "POST", entity.getAttributeMap().get("API Http method").getString()); } } } @@ -450,28 +447,6 @@ private Expression getStringListLiteral(List values) { .build(); } - private Expression getExpressionFor(String columnName, String alias) { - return Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder().setColumnName(columnName).setAlias(alias)) - .build(); - } - - private Expression getFunctionExpressionFor(FunctionType type, String columnName, String alias) { - return Expression.newBuilder() - .setFunction( - FunctionExpression.newBuilder() - .setFunction(type) - .setAlias(alias) - .addArguments( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder() - .setColumnName(columnName) - .setAlias(alias)))) - .build(); - } - private TimeAggregation getTimeAggregationFor(Expression expression) { return TimeAggregation.newBuilder() .setAggregation(expression) diff --git a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/explore/TimeAggregationsRequestHandlerTest.java b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/explore/TimeAggregationsRequestHandlerTest.java index e6abb5f3..70973dd5 100644 --- a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/explore/TimeAggregationsRequestHandlerTest.java +++ b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/explore/TimeAggregationsRequestHandlerTest.java @@ -5,7 +5,7 @@ import java.util.List; import org.hypertrace.core.query.service.client.QueryServiceClient; import org.hypertrace.gateway.service.common.AttributeMetadataProvider; -import org.hypertrace.gateway.service.v1.common.ColumnIdentifier; +import org.hypertrace.gateway.service.common.util.QueryExpressionUtil; import org.hypertrace.gateway.service.v1.common.Expression; import org.hypertrace.gateway.service.v1.common.FunctionExpression; import org.hypertrace.gateway.service.v1.common.FunctionType; @@ -34,11 +34,8 @@ public void intervalStartTimeOrderByShouldBeAddedToOrderByListAndAliasShouldMatc .setFunction(FunctionType.AVG) .setAlias("AVG_Duration") .addArguments( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder() - .setColumnName( - "Api.Trace.metrics.duration_millis")))))) + QueryExpressionUtil.buildAttributeExpression( + "Api.Trace.metrics.duration_millis"))))) .addTimeAggregation( TimeAggregation.newBuilder() .setPeriod(Period.newBuilder().setUnit("SECONDS").setValue(60)) @@ -49,11 +46,8 @@ public void intervalStartTimeOrderByShouldBeAddedToOrderByListAndAliasShouldMatc .setFunction(FunctionType.MAX) .setAlias("MAX_Duration") .addArguments( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder() - .setColumnName( - "Api.Trace.metrics.duration_millis")))))) + QueryExpressionUtil.buildAttributeExpression( + "Api.Trace.metrics.duration_millis"))))) .addOrderBy( OrderByExpression.newBuilder() .setOrder(SortOrder.DESC) @@ -64,11 +58,8 @@ public void intervalStartTimeOrderByShouldBeAddedToOrderByListAndAliasShouldMatc .setFunction(FunctionType.AVG) .setAlias("AVG_Duration_different_alias") .addArguments( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder() - .setColumnName( - "Api.Trace.metrics.duration_millis")))))) + QueryExpressionUtil.buildAttributeExpression( + "Api.Trace.metrics.duration_millis"))))) .build(); TimeAggregationsRequestHandler requestHandler = @@ -83,10 +74,7 @@ public void intervalStartTimeOrderByShouldBeAddedToOrderByListAndAliasShouldMatc OrderByExpression.newBuilder() .setOrder(SortOrder.ASC) .setExpression( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder() - .setColumnName(ColumnName.INTERVAL_START_TIME.name()))) + QueryExpressionUtil.buildAttributeExpression(ColumnName.INTERVAL_START_TIME.name())) .build(), orderByExpressions.get(0)); // Should switch out the alias in the OrderBy expression @@ -100,10 +88,8 @@ public void intervalStartTimeOrderByShouldBeAddedToOrderByListAndAliasShouldMatc .setFunction(FunctionType.AVG) .setAlias("AVG_Duration") .addArguments( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder() - .setColumnName("Api.Trace.metrics.duration_millis"))))) + QueryExpressionUtil.buildAttributeExpression( + "Api.Trace.metrics.duration_millis")))) .build(), orderByExpressions.get(1)); } @@ -122,18 +108,13 @@ public void intervalStartTimeOrderingNotAddedIfAlreadyRequested() { .setFunction(FunctionType.MAX) .setAlias("MAX_Duration") .addArguments( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder() - .setColumnName("duration")))))) + QueryExpressionUtil.buildAttributeExpression("duration"))))) .addOrderBy( OrderByExpression.newBuilder() .setOrder(SortOrder.DESC) .setExpression( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder() - .setColumnName(ColumnName.INTERVAL_START_TIME.name())))) + QueryExpressionUtil.buildAttributeExpression( + ColumnName.INTERVAL_START_TIME.name()))) .build(); TimeAggregationsRequestHandler requestHandler = @@ -148,10 +129,8 @@ public void intervalStartTimeOrderingNotAddedIfAlreadyRequested() { OrderByExpression.newBuilder() .setOrder(SortOrder.DESC) .setExpression( - Expression.newBuilder() - .setColumnIdentifier( - ColumnIdentifier.newBuilder() - .setColumnName(ColumnName.INTERVAL_START_TIME.name()))) + QueryExpressionUtil.buildAttributeExpression( + ColumnName.INTERVAL_START_TIME.name())) .build()), orderByExpressions); } diff --git a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/testutils/GatewayExpressionCreator.java b/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/testutils/GatewayExpressionCreator.java deleted file mode 100644 index 50295d7c..00000000 --- a/gateway-service-impl/src/test/java/org/hypertrace/gateway/service/testutils/GatewayExpressionCreator.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.hypertrace.gateway.service.testutils; - -import org.hypertrace.gateway.service.v1.common.Expression; -import org.hypertrace.gateway.service.v1.common.Filter; -import org.hypertrace.gateway.service.v1.common.LiteralConstant; -import org.hypertrace.gateway.service.v1.common.Operator; -import org.hypertrace.gateway.service.v1.common.Value; -import org.hypertrace.gateway.service.v1.common.ValueType; - -public class GatewayExpressionCreator { - public static Filter.Builder createFilter( - Expression.Builder lhs, Operator op, Expression.Builder rhs) { - return Filter.newBuilder().setLhs(lhs).setOperator(op).setRhs(rhs); - } - - public static Expression.Builder createLiteralExpression(Boolean value) { - return Expression.newBuilder() - .setLiteral( - LiteralConstant.newBuilder() - .setValue(Value.newBuilder().setBoolean(value).setValueType(ValueType.BOOL))); - } - - public static Expression.Builder createLiteralExpression(String value) { - return Expression.newBuilder() - .setLiteral( - LiteralConstant.newBuilder() - .setValue(Value.newBuilder().setString(value).setValueType(ValueType.STRING))); - } -} diff --git a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/aggregations-with-groupby-and-the-rest-deprecated.json b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/aggregations-with-groupby-and-the-rest-deprecated.json index 924353e3..6de9217c 100644 --- a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/aggregations-with-groupby-and-the-rest-deprecated.json +++ b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/aggregations-with-groupby-and-the-rest-deprecated.json @@ -7,8 +7,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "GE", @@ -23,8 +23,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "LT", @@ -43,8 +43,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiBoundaryType" + "attributeExpression": { + "attributeId": "API_TRACE.apiBoundaryType" } }, "operator": "EQ", @@ -66,8 +66,8 @@ "functionName": "AVG", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.duration" + "attributeExpression": { + "attributeId": "API_TRACE.duration" } } ], @@ -79,8 +79,8 @@ "functionName": "COUNT", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.apiTraceId" + "attributeExpression": { + "attributeId": "API_TRACE.apiTraceId" } } ], @@ -88,15 +88,15 @@ } }, { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } } ], "groupBy": [ { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } } ], @@ -402,8 +402,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "GE", @@ -418,8 +418,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "LT", @@ -438,8 +438,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiBoundaryType" + "attributeExpression": { + "attributeId": "API_TRACE.apiBoundaryType" } }, "operator": "EQ", @@ -455,8 +455,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, "operator": "NOT_IN", @@ -481,8 +481,8 @@ "functionName": "AVG", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.duration" + "attributeExpression": { + "attributeId": "API_TRACE.duration" } } ], @@ -494,8 +494,8 @@ "functionName": "COUNT", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.apiTraceId" + "attributeExpression": { + "attributeId": "API_TRACE.apiTraceId" } } ], diff --git a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/aggregations-with-groupby.json b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/aggregations-with-groupby.json index 129dd51e..c161c262 100644 --- a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/aggregations-with-groupby.json +++ b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/aggregations-with-groupby.json @@ -7,8 +7,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "GE", @@ -23,8 +23,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "LT", @@ -43,8 +43,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiBoundaryType" + "attributeExpression": { + "attributeId": "API_TRACE.apiBoundaryType" } }, "operator": "EQ", @@ -66,8 +66,8 @@ "functionName": "AVG", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.duration" + "attributeExpression": { + "attributeId": "API_TRACE.duration" } } ], @@ -79,8 +79,8 @@ "functionName": "COUNT", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.apiTraceId" + "attributeExpression": { + "attributeId": "API_TRACE.apiTraceId" } } ], @@ -88,15 +88,15 @@ } }, { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } } ], "groupBy": [ { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } } ], diff --git a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/aggregations-with-multiple-groupbys-and-the-rest-deprecated.json b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/aggregations-with-multiple-groupbys-and-the-rest-deprecated.json index e0a8a959..90394d95 100644 --- a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/aggregations-with-multiple-groupbys-and-the-rest-deprecated.json +++ b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/aggregations-with-multiple-groupbys-and-the-rest-deprecated.json @@ -7,8 +7,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "GE", @@ -23,8 +23,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "LT", @@ -43,8 +43,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiBoundaryType" + "attributeExpression": { + "attributeId": "API_TRACE.apiBoundaryType" } }, "operator": "EQ", @@ -66,8 +66,8 @@ "functionName": "AVG", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.duration" + "attributeExpression": { + "attributeId": "API_TRACE.duration" } } ], @@ -79,8 +79,8 @@ "functionName": "COUNT", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.apiTraceId" + "attributeExpression": { + "attributeId": "API_TRACE.apiTraceId" } } ], @@ -88,25 +88,25 @@ } }, { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, { - "columnIdentifier": { - "columnName": "API_TRACE.apiName" + "attributeExpression": { + "attributeId": "API_TRACE.apiName" } } ], "groupBy": [ { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, { - "columnIdentifier": { - "columnName": "API_TRACE.apiName" + "attributeExpression": { + "attributeId": "API_TRACE.apiName" } } ], @@ -478,8 +478,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "GE", @@ -494,8 +494,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "LT", @@ -514,8 +514,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiBoundaryType" + "attributeExpression": { + "attributeId": "API_TRACE.apiBoundaryType" } }, "operator": "EQ", @@ -535,8 +535,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, "operator": "NEQ", @@ -551,8 +551,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiName" + "attributeExpression": { + "attributeId": "API_TRACE.apiName" } }, "operator": "NEQ", @@ -572,8 +572,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, "operator": "NEQ", @@ -588,8 +588,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiName" + "attributeExpression": { + "attributeId": "API_TRACE.apiName" } }, "operator": "NEQ", @@ -609,8 +609,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, "operator": "NEQ", @@ -625,8 +625,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiName" + "attributeExpression": { + "attributeId": "API_TRACE.apiName" } }, "operator": "NEQ", @@ -646,8 +646,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, "operator": "NEQ", @@ -662,8 +662,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiName" + "attributeExpression": { + "attributeId": "API_TRACE.apiName" } }, "operator": "NEQ", @@ -683,8 +683,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, "operator": "NEQ", @@ -699,8 +699,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiName" + "attributeExpression": { + "attributeId": "API_TRACE.apiName" } }, "operator": "NEQ", @@ -720,8 +720,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, "operator": "NEQ", @@ -736,8 +736,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiName" + "attributeExpression": { + "attributeId": "API_TRACE.apiName" } }, "operator": "NEQ", @@ -757,8 +757,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, "operator": "NEQ", @@ -773,8 +773,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiName" + "attributeExpression": { + "attributeId": "API_TRACE.apiName" } }, "operator": "NEQ", @@ -794,8 +794,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, "operator": "NEQ", @@ -810,8 +810,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiName" + "attributeExpression": { + "attributeId": "API_TRACE.apiName" } }, "operator": "NEQ", @@ -831,8 +831,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, "operator": "NEQ", @@ -847,8 +847,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiName" + "attributeExpression": { + "attributeId": "API_TRACE.apiName" } }, "operator": "NEQ", @@ -868,8 +868,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, "operator": "NEQ", @@ -884,8 +884,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiName" + "attributeExpression": { + "attributeId": "API_TRACE.apiName" } }, "operator": "NEQ", @@ -912,8 +912,8 @@ "functionName": "AVG", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.duration" + "attributeExpression": { + "attributeId": "API_TRACE.duration" } } ], @@ -925,8 +925,8 @@ "functionName": "COUNT", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.apiTraceId" + "attributeExpression": { + "attributeId": "API_TRACE.apiTraceId" } } ], diff --git a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/group-by-with-group-limit-and-rest.json b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/group-by-with-group-limit-and-rest.json index 3da7a389..e26bdcf2 100644 --- a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/group-by-with-group-limit-and-rest.json +++ b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/group-by-with-group-limit-and-rest.json @@ -5,8 +5,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "GE", @@ -21,8 +21,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "LT", @@ -43,8 +43,8 @@ "functionName": "SUM", "arguments": [ { - "columnIdentifier": { - "columnName": "SERVICE.numCalls" + "attributeExpression": { + "attributeId": "SERVICE.numCalls" } } ], @@ -52,16 +52,16 @@ } }, { - "columnIdentifier": { - "columnName": "SERVICE.name", + "attributeExpression": { + "attributeId": "SERVICE.name", "alias": "SERVICE.name" } } ], "groupBy": [ { - "columnIdentifier": { - "columnName": "SERVICE.name", + "attributeExpression": { + "attributeId": "SERVICE.name", "alias": "SERVICE.name" } } @@ -352,8 +352,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "GE", @@ -368,8 +368,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "LT", @@ -388,8 +388,9 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.name" + "attributeExpression": { + "attributeId": "SERVICE.name", + "alias": "SERVICE.name" } }, "operator": "NOT_IN", @@ -415,8 +416,8 @@ "functionName": "SUM", "arguments": [ { - "columnIdentifier": { - "columnName": "SERVICE.numCalls" + "attributeExpression": { + "attributeId": "SERVICE.numCalls" } } ], diff --git a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/group-by-with-group-limit.json b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/group-by-with-group-limit.json index c7923771..4828b96d 100644 --- a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/group-by-with-group-limit.json +++ b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/group-by-with-group-limit.json @@ -5,8 +5,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "GE", @@ -21,8 +21,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "LT", @@ -43,8 +43,8 @@ "functionName": "SUM", "arguments": [ { - "columnIdentifier": { - "columnName": "SERVICE.numCalls" + "attributeExpression": { + "attributeId": "SERVICE.numCalls" } } ], @@ -52,16 +52,16 @@ } }, { - "columnIdentifier": { - "columnName": "SERVICE.name", + "attributeExpression": { + "attributeId": "SERVICE.name", "alias": "SERVICE.name" } } ], "groupBy": [ { - "columnIdentifier": { - "columnName": "SERVICE.name", + "attributeExpression": { + "attributeId": "SERVICE.name", "alias": "SERVICE.name" } } diff --git a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/grouped-time-aggregation-with-group-limit-and-the-rest.json b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/grouped-time-aggregation-with-group-limit-and-the-rest.json index 6e197ecc..60c5ddec 100644 --- a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/grouped-time-aggregation-with-group-limit-and-the-rest.json +++ b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/grouped-time-aggregation-with-group-limit-and-the-rest.json @@ -5,8 +5,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "GE", @@ -21,8 +21,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "LT", @@ -43,8 +43,8 @@ "functionName": "SUM", "arguments": [ { - "columnIdentifier": { - "columnName": "SERVICE.numCalls" + "attributeExpression": { + "attributeId": "SERVICE.numCalls" } } ], @@ -52,16 +52,16 @@ } }, { - "columnIdentifier": { - "columnName": "SERVICE.name", + "attributeExpression": { + "attributeId": "SERVICE.name", "alias": "SERVICE.name" } } ], "groupBy": [ { - "columnIdentifier": { - "columnName": "SERVICE.name", + "attributeExpression": { + "attributeId": "SERVICE.name", "alias": "SERVICE.name" } } @@ -352,8 +352,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "GE", @@ -368,8 +368,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "LT", @@ -388,8 +388,9 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.name" + "attributeExpression": { + "attributeId": "SERVICE.name", + "alias": "SERVICE.name" } }, "operator": "IN", @@ -415,8 +416,8 @@ "functionName": "SUM", "arguments": [ { - "columnIdentifier": { - "columnName": "SERVICE.numCalls" + "attributeExpression": { + "attributeId": "SERVICE.numCalls" } } ], @@ -424,8 +425,8 @@ } }, { - "columnIdentifier": { - "columnName": "SERVICE.name", + "attributeExpression": { + "attributeId": "SERVICE.name", "alias": "SERVICE.name" } } @@ -436,8 +437,8 @@ "functionName": "dateTimeConvert", "arguments": [ { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, { @@ -465,8 +466,8 @@ } }, { - "columnIdentifier": { - "columnName": "SERVICE.name", + "attributeExpression": { + "attributeId": "SERVICE.name", "alias": "SERVICE.name" } } @@ -2294,8 +2295,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "GE", @@ -2310,8 +2311,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "LT", @@ -2330,8 +2331,9 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.name" + "attributeExpression": { + "attributeId": "SERVICE.name", + "alias": "SERVICE.name" } }, "operator": "NOT_IN", @@ -2357,8 +2359,8 @@ "functionName": "SUM", "arguments": [ { - "columnIdentifier": { - "columnName": "SERVICE.numCalls" + "attributeExpression": { + "attributeId": "SERVICE.numCalls" } } ], @@ -2372,8 +2374,8 @@ "functionName": "dateTimeConvert", "arguments": [ { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, { diff --git a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/grouped-time-aggregation-with-group-limit.json b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/grouped-time-aggregation-with-group-limit.json index 6321e760..c063416c 100644 --- a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/grouped-time-aggregation-with-group-limit.json +++ b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/grouped-time-aggregation-with-group-limit.json @@ -5,8 +5,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "GE", @@ -21,8 +21,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "LT", @@ -43,8 +43,8 @@ "functionName": "SUM", "arguments": [ { - "columnIdentifier": { - "columnName": "SERVICE.numCalls" + "attributeExpression": { + "attributeId": "SERVICE.numCalls" } } ], @@ -52,16 +52,16 @@ } }, { - "columnIdentifier": { - "columnName": "SERVICE.name", + "attributeExpression": { + "attributeId": "SERVICE.name", "alias": "SERVICE.name" } } ], "groupBy": [ { - "columnIdentifier": { - "columnName": "SERVICE.name", + "attributeExpression": { + "attributeId": "SERVICE.name", "alias": "SERVICE.name" } } @@ -352,8 +352,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "GE", @@ -368,8 +368,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, "operator": "LT", @@ -388,8 +388,9 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "SERVICE.name" + "attributeExpression": { + "attributeId": "SERVICE.name", + "alias": "SERVICE.name" } }, "operator": "IN", @@ -415,8 +416,8 @@ "functionName": "SUM", "arguments": [ { - "columnIdentifier": { - "columnName": "SERVICE.numCalls" + "attributeExpression": { + "attributeId": "SERVICE.numCalls" } } ], @@ -424,8 +425,8 @@ } }, { - "columnIdentifier": { - "columnName": "SERVICE.name", + "attributeExpression": { + "attributeId": "SERVICE.name", "alias": "SERVICE.name" } } @@ -436,8 +437,8 @@ "functionName": "dateTimeConvert", "arguments": [ { - "columnIdentifier": { - "columnName": "SERVICE.startTime" + "attributeExpression": { + "attributeId": "SERVICE.startTime" } }, { @@ -465,8 +466,8 @@ } }, { - "columnIdentifier": { - "columnName": "SERVICE.name", + "attributeExpression": { + "attributeId": "SERVICE.name", "alias": "SERVICE.name" } } diff --git a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/simple-aggregations.json b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/simple-aggregations.json index 0937c402..b6b93677 100644 --- a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/simple-aggregations.json +++ b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/simple-aggregations.json @@ -7,8 +7,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "GE", @@ -23,8 +23,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "LT", @@ -43,8 +43,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiBoundaryType" + "attributeExpression": { + "attributeId": "API_TRACE.apiBoundaryType" } }, "operator": "EQ", @@ -66,8 +66,8 @@ "functionName": "AVG", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.duration" + "attributeExpression": { + "attributeId": "API_TRACE.duration" } } ], @@ -79,8 +79,8 @@ "functionName": "PERCENTILE95", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.duration" + "attributeExpression": { + "attributeId": "API_TRACE.duration" } } ], @@ -92,8 +92,8 @@ "functionName": "COUNT", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.duration" + "attributeExpression": { + "attributeId": "API_TRACE.duration" } } ], @@ -104,8 +104,8 @@ "function": { "functionName": "AVGRATE", "arguments": [{ - "columnIdentifier": { - "columnName": "API_TRACE.duration" + "attributeExpression": { + "attributeId": "API_TRACE.duration" } }, { "literal": { @@ -125,8 +125,8 @@ "functionName": "AVG", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.duration" + "attributeExpression": { + "attributeId": "API_TRACE.duration" } } ], diff --git a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/simple-selection.json b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/simple-selection.json index 8e26704a..23ac2ec9 100644 --- a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/simple-selection.json +++ b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/simple-selection.json @@ -7,8 +7,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "GE", @@ -23,8 +23,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "LT", @@ -43,8 +43,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiBoundaryType" + "attributeExpression": { + "attributeId": "API_TRACE.apiBoundaryType" } }, "operator": "EQ", @@ -62,26 +62,26 @@ }, "selection": [ { - "columnIdentifier": { - "columnName": "API_TRACE.duration" + "attributeExpression": { + "attributeId": "API_TRACE.duration" } }, { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, { - "columnIdentifier": { - "columnName": "API_TRACE.apiName" + "attributeExpression": { + "attributeId": "API_TRACE.apiName" } } ], "orderBy": [ { "expression": { - "columnIdentifier": { - "columnName": "API_TRACE.serviceName" + "attributeExpression": { + "attributeId": "API_TRACE.serviceName" } }, "order": "DESC" diff --git a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/time-aggregations-space-filtered.json b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/time-aggregations-space-filtered.json index ea932723..d8bb86a2 100644 --- a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/time-aggregations-space-filtered.json +++ b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/time-aggregations-space-filtered.json @@ -7,8 +7,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "GE", @@ -23,8 +23,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "LT", @@ -43,8 +43,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiBoundaryType" + "attributeExpression": { + "attributeId": "API_TRACE.apiBoundaryType" } }, "operator": "EQ", @@ -60,8 +60,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.spaceIds" + "attributeExpression": { + "attributeId": "API_TRACE.spaceIds" } }, "operator": "EQ", @@ -81,8 +81,8 @@ "functionName": "AVG", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.duration" + "attributeExpression": { + "attributeId": "API_TRACE.duration" } } ], @@ -94,8 +94,8 @@ "functionName": "COUNT", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.traceId" + "attributeExpression": { + "attributeId": "API_TRACE.traceId" } } ], @@ -109,8 +109,8 @@ "functionName": "dateTimeConvert", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, { diff --git a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/time-aggregations.json b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/time-aggregations.json index 5afec29d..cd54be1e 100644 --- a/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/time-aggregations.json +++ b/gateway-service-impl/src/test/resources/query-service-requests-and-responses/explore/time-aggregations.json @@ -7,8 +7,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "GE", @@ -23,8 +23,8 @@ }, { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, "operator": "LT", @@ -43,8 +43,8 @@ "childFilter": [ { "lhs": { - "columnIdentifier": { - "columnName": "API_TRACE.apiBoundaryType" + "attributeExpression": { + "attributeId": "API_TRACE.apiBoundaryType" } }, "operator": "EQ", @@ -66,8 +66,8 @@ "functionName": "AVG", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.duration" + "attributeExpression": { + "attributeId": "API_TRACE.duration" } } ], @@ -79,8 +79,8 @@ "functionName": "COUNT", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.traceId" + "attributeExpression": { + "attributeId": "API_TRACE.traceId" } } ], @@ -94,8 +94,8 @@ "functionName": "dateTimeConvert", "arguments": [ { - "columnIdentifier": { - "columnName": "API_TRACE.startTime" + "attributeExpression": { + "attributeId": "API_TRACE.startTime" } }, { diff --git a/gateway-service/build.gradle.kts b/gateway-service/build.gradle.kts index 99272e17..b872b2cd 100644 --- a/gateway-service/build.gradle.kts +++ b/gateway-service/build.gradle.kts @@ -8,16 +8,16 @@ plugins { dependencies { implementation(project(":gateway-service-impl")) - implementation("org.hypertrace.core.grpcutils:grpc-server-utils:0.6.2") + implementation("org.hypertrace.core.grpcutils:grpc-server-utils:0.7.0") implementation("org.hypertrace.core.serviceframework:platform-service-framework:0.1.29") - implementation("io.grpc:grpc-netty:1.42.0") + implementation("io.grpc:grpc-netty:1.43.1") // Logging implementation("org.slf4j:slf4j-api:1.7.30") implementation("org.apache.logging.log4j:log4j-api:2.16.0") implementation("org.apache.logging.log4j:log4j-core:2.16.0") - implementation("org.apache.logging.log4j:log4j-slf4j-impl:2.17.0") + implementation("org.apache.logging.log4j:log4j-slf4j-impl:2.17.1") // Config implementation("com.typesafe:config:1.4.1")