use of org.hypertrace.gateway.service.entity.EntityKey in project gateway-service by hypertrace.
the class EntityDataServiceEntityFetcher method getEntities.
@Override
public EntityFetcherResponse getEntities(EntitiesRequestContext requestContext, EntitiesRequest entitiesRequest) {
List<String> entityIdAttributeIds = AttributeMetadataUtil.getIdAttributeIds(attributeMetadataProvider, entityIdColumnsConfigs, requestContext, entitiesRequest.getEntityType());
Map<String, List<String>> requestedAliasesByEntityIdAttributeIds = getExpectedResultNamesForEachAttributeId(entitiesRequest.getSelectionList(), entityIdAttributeIds);
EntityQueryRequest.Builder builder = EntityQueryRequest.newBuilder().setEntityType(entitiesRequest.getEntityType()).setFilter(EntityServiceAndGatewayServiceConverter.convertToEntityServiceFilter(entitiesRequest.getFilter())).addAllSelection(entityIdAttributeIds.stream().map(entityIdAttr -> EntityServiceAndGatewayServiceConverter.createColumnExpression(entityIdAttr).build()).collect(Collectors.toList()));
// add time filter for supported scope
if (!entitiesRequest.getIncludeNonLiveEntities()) {
EntityServiceAndGatewayServiceConverter.addBetweenTimeFilter(entitiesRequest.getStartTimeMillis(), entitiesRequest.getEndTimeMillis(), attributeMetadataProvider, entitiesRequest, builder, requestContext);
}
// Add all expressions in the select that are already not part of the EntityID attributes
entitiesRequest.getSelectionList().stream().filter(ExpressionReader::isAttributeSelection).filter(expression -> ExpressionReader.getAttributeIdFromAttributeSelection(expression).map(attributeId -> !entityIdAttributeIds.contains(attributeId)).orElse(true)).forEach(expression -> builder.addSelection(EntityServiceAndGatewayServiceConverter.convertToEntityServiceExpression(expression)));
int limit = entitiesRequest.getLimit();
if (limit > 0) {
builder.setLimit(limit);
}
int offset = entitiesRequest.getOffset();
if (offset > 0) {
builder.setOffset(offset);
}
if (!entitiesRequest.getOrderByList().isEmpty()) {
builder.addAllOrderBy(EntityServiceAndGatewayServiceConverter.convertToOrderByExpressions(entitiesRequest.getOrderByList()));
}
EntityQueryRequest entityQueryRequest = builder.build();
LOG.debug("Sending Query to EDS ======== \n {}", entityQueryRequest);
Iterator<ResultSetChunk> resultSetChunkIterator = entityQueryServiceClient.execute(builder.build(), requestContext.getHeaders());
Map<String, AttributeMetadata> resultMetadataMap = this.getAttributeMetadataByAlias(requestContext, entitiesRequest);
// We want to retain the order as returned from the respective source. Hence using a
// LinkedHashMap
Map<EntityKey, Builder> entityBuilders = new LinkedHashMap<>();
while (resultSetChunkIterator.hasNext()) {
ResultSetChunk chunk = resultSetChunkIterator.next();
LOG.debug("Received chunk: {}", chunk);
if (chunk.getRowCount() < 1) {
break;
}
for (Row row : chunk.getRowList()) {
// Construct the entity id from the entityIdAttributes columns
EntityKey entityKey = EntityKey.of(IntStream.range(0, entityIdAttributeIds.size()).mapToObj(value -> row.getColumn(value).getString()).toArray(String[]::new));
Builder entityBuilder = entityBuilders.computeIfAbsent(entityKey, k -> Entity.newBuilder());
entityBuilder.setEntityType(entitiesRequest.getEntityType());
entityBuilder.setId(entityKey.toString());
// as post processing.
for (int i = 0; i < entityIdAttributeIds.size(); i++) {
entityBuilder.putAttribute(entityIdAttributeIds.get(i), Value.newBuilder().setString(entityKey.getAttributes().get(i)).setValueType(ValueType.STRING).build());
}
requestedAliasesByEntityIdAttributeIds.forEach((attributeId, requestedAliasList) -> requestedAliasList.forEach(requestedAlias -> entityBuilder.putAttribute(requestedAlias, entityBuilder.getAttributeOrThrow(attributeId))));
for (int i = entityIdAttributeIds.size(); i < chunk.getResultSetMetadata().getColumnMetadataCount(); i++) {
String resultName = chunk.getResultSetMetadata().getColumnMetadata(i).getColumnName();
AttributeMetadata attributeMetadata = resultMetadataMap.get(resultName);
entityBuilder.putAttribute(resultName, EntityServiceAndGatewayServiceConverter.convertQueryValueToGatewayValue(row.getColumn(i), attributeMetadata));
}
}
}
return new EntityFetcherResponse(entityBuilders);
}
use of org.hypertrace.gateway.service.entity.EntityKey in project gateway-service by hypertrace.
the class EntityInteractionsFetcher method parseResultSet.
private void parseResultSet(String entityType, String otherEntityType, Collection<Expression> selections, Map<String, FunctionExpression> metricToAggFunction, Iterator<ResultSetChunk> resultset, boolean incoming, Map<EntityKey, Builder> entityIdToBuilders, RequestContext requestContext) {
Map<String, AttributeMetadata> attributeMetadataMap = metadataProvider.getAttributesMetadata(requestContext, SCOPE);
Map<String, AttributeKind> aliasToAttributeKind = MetricAggregationFunctionUtil.getValueTypeForFunctionType(metricToAggFunction, attributeMetadataMap);
while (resultset.hasNext()) {
ResultSetChunk chunk = resultset.next();
if (LOG.isDebugEnabled()) {
LOG.debug("Received chunk: " + chunk.toString());
}
if (chunk.getRowCount() < 1) {
break;
}
for (Row row : chunk.getRowList()) {
// Construct the from/to EntityKeys from the columns
List<String> idColumns = getEntityIdColumnsFromInteraction(DomainEntityType.valueOf(entityType.toUpperCase()), // Note: We add the selections it in this order
!incoming);
EntityKey entityId = EntityKey.of(IntStream.range(0, idColumns.size()).mapToObj(value -> row.getColumn(value).getString()).toArray(String[]::new));
List<String> otherIdColumns = getEntityIdColumnsFromInteraction(DomainEntityType.valueOf(otherEntityType.toUpperCase()), incoming);
EntityKey otherEntityId = EntityKey.of(IntStream.range(idColumns.size(), idColumns.size() + otherIdColumns.size()).mapToObj(value -> row.getColumn(value).getString()).toArray(String[]::new));
EntityInteraction.Builder interaction = EntityInteraction.newBuilder();
addInteractionEdges(interaction, selections, incoming ? otherEntityType : entityType, incoming ? otherEntityId : entityId, incoming ? entityType : otherEntityType, incoming ? entityId : otherEntityId);
for (int i = idColumns.size() + otherIdColumns.size(); i < chunk.getResultSetMetadata().getColumnMetadataCount(); i++) {
ColumnMetadata metadata = chunk.getResultSetMetadata().getColumnMetadata(i);
// Ignore the count column since we introduced that ourselves into the query.
if (StringUtils.equalsIgnoreCase(COUNT_COLUMN_NAME, metadata.getColumnName())) {
continue;
}
// Check if this is an attribute vs metric and set it accordingly on the interaction.
if (metricToAggFunction.containsKey(metadata.getColumnName())) {
Value value = QueryAndGatewayDtoConverter.convertToGatewayValueForMetricValue(aliasToAttributeKind, attributeMetadataMap, metadata, row.getColumn(i));
interaction.putMetrics(metadata.getColumnName(), AggregatedMetricValue.newBuilder().setValue(value).setFunction(metricToAggFunction.get(metadata.getColumnName()).getFunction()).build());
} else {
interaction.putAttribute(metadata.getColumnName(), QueryAndGatewayDtoConverter.convertQueryValueToGatewayValue(row.getColumn(i), attributeMetadataMap.get(metadata.getColumnName())));
}
}
if (incoming) {
entityIdToBuilders.get(entityId).addIncomingInteraction(interaction);
} else {
entityIdToBuilders.get(entityId).addOutgoingInteraction(interaction);
}
if (LOG.isDebugEnabled()) {
LOG.debug(interaction.build().toString());
}
}
}
}
use of org.hypertrace.gateway.service.entity.EntityKey in project gateway-service by hypertrace.
the class QueryServiceEntityFetcher method getEntities.
@Override
public EntityFetcherResponse getEntities(EntitiesRequestContext requestContext, EntitiesRequest entitiesRequest) {
Map<String, AttributeMetadata> attributeMetadataMap = attributeMetadataProvider.getAttributesMetadata(requestContext, entitiesRequest.getEntityType());
Map<String, AttributeMetadata> resultKeyToAttributeMetadataMap = this.remapAttributeMetadataByResultName(entitiesRequest, attributeMetadataMap);
// Validate EntitiesRequest
entitiesRequestValidator.validate(entitiesRequest, attributeMetadataMap);
List<String> entityIdAttributeIds = AttributeMetadataUtil.getIdAttributeIds(attributeMetadataProvider, entityIdColumnsConfigs, requestContext, entitiesRequest.getEntityType());
List<org.hypertrace.gateway.service.v1.common.Expression> aggregates = ExpressionReader.getFunctionExpressions(entitiesRequest.getSelectionList());
Map<String, List<String>> requestedAliasesByEntityIdAttributeIds = getExpectedResultNamesForEachAttributeId(entitiesRequest.getSelectionList(), entityIdAttributeIds);
QueryRequest.Builder builder = constructSelectionQuery(requestContext, entitiesRequest, entityIdAttributeIds, aggregates);
adjustLimitAndOffset(builder, entitiesRequest.getLimit(), entitiesRequest.getOffset());
if (!entitiesRequest.getOrderByList().isEmpty()) {
// Order by from the request.
builder.addAllOrderBy(QueryAndGatewayDtoConverter.convertToQueryOrderByExpressions(entitiesRequest.getOrderByList()));
}
QueryRequest queryRequest = builder.build();
LOG.debug("Sending Query to Query Service ======== \n {}", queryRequest);
Iterator<ResultSetChunk> resultSetChunkIterator = queryServiceClient.executeQuery(queryRequest, requestContext.getHeaders(), requestTimeout);
// We want to retain the order as returned from the respective source. Hence using a
// LinkedHashMap
Map<EntityKey, Entity.Builder> entityBuilders = new LinkedHashMap<>();
while (resultSetChunkIterator.hasNext()) {
ResultSetChunk chunk = resultSetChunkIterator.next();
LOG.debug("Received chunk: {}", chunk);
if (chunk.getRowCount() < 1) {
break;
}
for (Row row : chunk.getRowList()) {
// Construct the entity id from the entityIdAttributeIds columns
EntityKey entityKey = EntityKey.of(IntStream.range(0, entityIdAttributeIds.size()).mapToObj(value -> row.getColumn(value).getString()).toArray(String[]::new));
Builder entityBuilder = entityBuilders.computeIfAbsent(entityKey, k -> Entity.newBuilder());
entityBuilder.setEntityType(entitiesRequest.getEntityType());
entityBuilder.setId(entityKey.toString());
// as post processing.
for (int i = 0; i < entityIdAttributeIds.size(); i++) {
entityBuilder.putAttribute(entityIdAttributeIds.get(i), Value.newBuilder().setString(entityKey.getAttributes().get(i)).setValueType(ValueType.STRING).build());
}
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);
org.hypertrace.core.query.service.api.Value columnValue = row.getColumn(i);
buildEntity(entityBuilder, requestContext, metadata, columnValue, resultKeyToAttributeMetadataMap, aggregates.isEmpty());
}
}
}
return new EntityFetcherResponse(entityBuilders);
}
use of org.hypertrace.gateway.service.entity.EntityKey in project gateway-service by hypertrace.
the class QueryServiceEntityFetcher method getTimeAggregatedMetrics.
@Override
public EntityFetcherResponse getTimeAggregatedMetrics(EntitiesRequestContext requestContext, EntitiesRequest entitiesRequest) {
// No need to make execute the rest of this if there are no TimeAggregations in the request.
if (entitiesRequest.getTimeAggregationCount() == 0) {
return new EntityFetcherResponse();
}
// Only supported filter is entityIds IN ["id1", "id2", "id3"]
List<String> idColumns = AttributeMetadataUtil.getIdAttributeIds(attributeMetadataProvider, entityIdColumnsConfigs, requestContext, entitiesRequest.getEntityType());
String timeColumn = AttributeMetadataUtil.getTimestampAttributeId(attributeMetadataProvider, requestContext, entitiesRequest.getEntityType());
Map<String, AttributeMetadata> attributeMetadataMap = attributeMetadataProvider.getAttributesMetadata(requestContext, entitiesRequest.getEntityType());
Map<String, AttributeMetadata> resultKeyToAttributeMetadataMap = this.remapAttributeMetadataByResultName(entitiesRequest, attributeMetadataMap);
entitiesRequestValidator.validate(entitiesRequest, attributeMetadataMap);
entitiesRequest.getTimeAggregationList().forEach(timeAggregation -> requestContext.mapAliasToTimeAggregation(timeAggregation.getAggregation().getFunction().getAlias(), timeAggregation));
// First group the Aggregations based on the period so that we can issue separate queries
// to QueryService for each different Period.
Collection<List<TimeAggregation>> result = entitiesRequest.getTimeAggregationList().stream().collect(Collectors.groupingBy(TimeAggregation::getPeriod)).values();
Map<EntityKey, Map<String, MetricSeries.Builder>> entityMetricSeriesMap = new LinkedHashMap<>();
for (List<TimeAggregation> batch : result) {
Period period = batch.get(0).getPeriod();
ChronoUnit unit = ChronoUnit.valueOf(period.getUnit());
long periodSecs = Duration.of(period.getValue(), unit).getSeconds();
QueryRequest request = buildTimeSeriesQueryRequest(entitiesRequest, requestContext, periodSecs, batch, idColumns, timeColumn);
if (LOG.isDebugEnabled()) {
LOG.debug("Sending time series queryRequest to query service: ======== \n {}", request.toString());
}
Iterator<ResultSetChunk> resultSetChunkIterator = queryServiceClient.executeQuery(request, requestContext.getHeaders(), requestTimeout);
while (resultSetChunkIterator.hasNext()) {
ResultSetChunk chunk = resultSetChunkIterator.next();
if (LOG.isDebugEnabled()) {
LOG.debug("Received chunk: " + chunk.toString());
}
if (chunk.getRowCount() < 1) {
break;
}
if (!chunk.hasResultSetMetadata()) {
LOG.warn("Chunk doesn't have result metadata so couldn't process the response.");
break;
}
for (Row row : chunk.getRowList()) {
// Construct the entity id from the entityIdAttributeIds columns
EntityKey entityKey = EntityKey.of(IntStream.range(0, idColumns.size()).mapToObj(value -> row.getColumn(value).getString()).toArray(String[]::new));
Map<String, MetricSeries.Builder> metricSeriesMap = entityMetricSeriesMap.computeIfAbsent(entityKey, k -> new LinkedHashMap<>());
Interval.Builder intervalBuilder = Interval.newBuilder();
// Second column is the time column
Value value = QueryAndGatewayDtoConverter.convertQueryValueToGatewayValue(row.getColumn(idColumns.size()));
if (value.getValueType() == ValueType.STRING) {
long startTime = Long.parseLong(value.getString());
long endTime = startTime + TimeUnit.SECONDS.toMillis(periodSecs);
intervalBuilder.setStartTimeMillis(startTime);
intervalBuilder.setEndTimeMillis(endTime);
for (int i = idColumns.size() + 1; i < chunk.getResultSetMetadata().getColumnMetadataCount(); i++) {
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.getValueTypeForFunctionType(functionType, functionAttributeMetadata), resultKeyToAttributeMetadataMap, metadata, row.getColumn(i));
List<org.hypertrace.gateway.service.v1.common.Expression> healthExpressions = timeAggregation.getAggregation().getFunction().getArgumentsList().stream().filter(org.hypertrace.gateway.service.v1.common.Expression::hasHealth).collect(Collectors.toList());
Preconditions.checkArgument(healthExpressions.size() <= 1);
Health health = Health.NOT_COMPUTED;
MetricSeries.Builder seriesBuilder = metricSeriesMap.computeIfAbsent(metadata.getColumnName(), k -> getMetricSeriesBuilder(timeAggregation));
seriesBuilder.addValue(Interval.newBuilder(intervalBuilder.build()).setValue(convertedValue).setHealth(health));
}
} else {
LOG.warn("Was expecting STRING values only but received valueType: {}", value.getValueType());
}
}
}
}
Map<EntityKey, Entity.Builder> resultMap = new LinkedHashMap<>();
for (Map.Entry<EntityKey, Map<String, MetricSeries.Builder>> entry : entityMetricSeriesMap.entrySet()) {
Entity.Builder entityBuilder = Entity.newBuilder().setEntityType(entitiesRequest.getEntityType()).setId(entry.getKey().toString()).putAllMetricSeries(entry.getValue().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> getSortedMetricSeries(e.getValue()))));
for (int i = 0; i < idColumns.size(); i++) {
entityBuilder.putAttribute(idColumns.get(i), Value.newBuilder().setString(entry.getKey().getAttributes().get(i)).setValueType(ValueType.STRING).build());
}
resultMap.put(entry.getKey(), entityBuilder);
}
return new EntityFetcherResponse(resultMap);
}
use of org.hypertrace.gateway.service.entity.EntityKey in project gateway-service by hypertrace.
the class ExecutionVisitorTest method test_visitDataFetcherNodeWithoutPagination.
@Test
public void test_visitDataFetcherNodeWithoutPagination() {
long startTime = 0;
long endTime = 10;
String tenantId = "TENANT_ID";
Map<String, String> requestHeaders = Map.of("x-tenant-id", tenantId);
AttributeScope entityType = AttributeScope.API;
Expression selectionExpression = buildExpression(API_NAME_ATTR);
EntitiesRequest entitiesRequest = EntitiesRequest.newBuilder().setEntityType(entityType.name()).setStartTimeMillis(startTime).setEndTimeMillis(endTime).addSelection(selectionExpression).setFilter(generateEQFilter(API_DISCOVERY_STATE, "DISCOVERED")).build();
EntitiesRequestContext entitiesRequestContext = new EntitiesRequestContext(tenantId, startTime, endTime, entityType.name(), "API.startTime", requestHeaders);
Map<EntityKey, Builder> entityKeyBuilderResponseMap = Map.of(EntityKey.of("entity-id-0"), Entity.newBuilder().putAttribute("API.name", getStringValue("entity-0")), EntityKey.of("entity-id-1"), Entity.newBuilder().putAttribute("API.name", getStringValue("entity-1")), EntityKey.of("entity-id-2"), Entity.newBuilder().putAttribute("API.name", getStringValue("entity-2")));
EntityFetcherResponse entityFetcherResponse = new EntityFetcherResponse(entityKeyBuilderResponseMap);
when(expressionContext.getSourceToSelectionExpressionMap()).thenReturn(Map.of("QS", List.of(selectionExpression)));
when(executionContext.getEntitiesRequest()).thenReturn(entitiesRequest);
when(executionContext.getTenantId()).thenReturn(tenantId);
when(executionContext.getRequestHeaders()).thenReturn(requestHeaders);
when(executionContext.getTimestampAttributeId()).thenReturn("API.startTime");
when(queryServiceEntityFetcher.getEntities(eq(entitiesRequestContext), eq(entitiesRequest))).thenReturn(entityFetcherResponse);
when(queryServiceEntityFetcher.getTimeAggregatedMetrics(eq(entitiesRequestContext), eq(entitiesRequest))).thenReturn(new EntityFetcherResponse());
// no pagination in data fetcher node
DataFetcherNode dataFetcherNode = new DataFetcherNode("QS", entitiesRequest.getFilter());
compareEntityResponses(new EntityResponse(entityFetcherResponse, entityFetcherResponse.getEntityKeyBuilderMap().size()), executionVisitor.visit(dataFetcherNode));
verify(queryServiceEntityFetcher, times(1)).getEntities(any(), any());
}
Aggregations