Search in sources :

Example 1 with StructuredTraceGraph

use of org.hypertrace.core.datamodel.shared.StructuredTraceGraph in project hypertrace-ingester by hypertrace.

the class AbstractBackendEntityEnricher method enrichTrace.

// At trace level, based on the next span to identify if a backend entity is actually a service
// entity.
@Override
public void enrichTrace(StructuredTrace trace) {
    try {
        StructuredTraceGraph structuredTraceGraph = buildGraph(trace);
        trace.getEventList().stream().filter(event -> EnrichedSpanUtils.isExitSpan(event) && SpanAttributeUtils.isLeafSpan(structuredTraceGraph, event) && canResolveBackend(structuredTraceGraph, event)).map(event -> Pair.of(event, resolve(event, trace, structuredTraceGraph))).filter(pair -> pair.getRight().isPresent()).filter(pair -> isValidBackendEntity(trace, pair.getLeft(), pair.getRight().get())).forEach(pair -> decorateWithBackendEntity(pair.getRight().get(), pair.getLeft(), trace));
    } catch (Exception ex) {
        LOGGER.error("An error occurred while enriching backend", ex);
    }
}
Also used : RequestContext(org.hypertrace.core.grpcutils.context.RequestContext) EnrichedSpanUtils(org.hypertrace.traceenricher.enrichedspan.constants.utils.EnrichedSpanUtils) EntityConstants(org.hypertrace.entity.service.constants.EntityConstants) BackendInfo(org.hypertrace.traceenricher.enrichment.enrichers.resolver.backend.BackendInfo) AttributeValueCreator(org.hypertrace.core.datamodel.shared.trace.AttributeValueCreator) LoggerFactory(org.slf4j.LoggerFactory) HashMap(java.util.HashMap) StringUtils(org.apache.commons.lang3.StringUtils) LinkedHashMap(java.util.LinkedHashMap) StructuredTraceGraph(org.hypertrace.core.datamodel.shared.StructuredTraceGraph) Pair(org.apache.commons.lang3.tuple.Pair) BackendType(org.hypertrace.traceenricher.enrichment.enrichers.BackendType) AttributeValue(org.hypertrace.entity.data.service.v1.AttributeValue) Map(java.util.Map) BackendProvider(org.hypertrace.traceenricher.enrichment.enrichers.backend.provider.BackendProvider) EnrichedSpanConstants(org.hypertrace.traceenricher.enrichedspan.constants.EnrichedSpanConstants) Entity(org.hypertrace.entity.data.service.v1.Entity) HexUtils(org.hypertrace.core.datamodel.shared.HexUtils) SpanAttributeUtils(org.hypertrace.core.datamodel.shared.SpanAttributeUtils) Backend(org.hypertrace.traceenricher.enrichedspan.constants.v1.Backend) EntityType(org.hypertrace.entity.v1.entitytype.EntityType) Nullable(javax.annotation.Nullable) StructuredTrace(org.hypertrace.core.datamodel.StructuredTrace) Logger(org.slf4j.Logger) SpanSemanticConventionUtils(org.hypertrace.semantic.convention.utils.span.SpanSemanticConventionUtils) Config(com.typesafe.config.Config) AbstractTraceEnricher(org.hypertrace.traceenricher.enrichment.AbstractTraceEnricher) BackendAttribute(org.hypertrace.entity.constants.v1.BackendAttribute) EnricherUtil(org.hypertrace.traceenricher.util.EnricherUtil) Event(org.hypertrace.core.datamodel.Event) EdsClient(org.hypertrace.entity.data.service.client.EdsClient) ClientRegistry(org.hypertrace.traceenricher.enrichment.clients.ClientRegistry) EntityCache(org.hypertrace.traceenricher.enrichment.enrichers.cache.EntityCache) ExecutionException(java.util.concurrent.ExecutionException) List(java.util.List) EntityAvroConverter(org.hypertrace.traceenricher.util.EntityAvroConverter) Optional(java.util.Optional) VisibleForTesting(com.google.common.annotations.VisibleForTesting) Collections(java.util.Collections) Joiner(com.google.common.base.Joiner) Builder(org.hypertrace.entity.data.service.v1.Entity.Builder) StructuredTraceGraph(org.hypertrace.core.datamodel.shared.StructuredTraceGraph) ExecutionException(java.util.concurrent.ExecutionException)

Example 2 with StructuredTraceGraph

use of org.hypertrace.core.datamodel.shared.StructuredTraceGraph in project hypertrace-ingester by hypertrace.

the class ApiTraceGraph method buildApiNodeEdges.

private void buildApiNodeEdges(StructuredTraceGraph graph) {
    // 4. connect the exit boundary and entry boundary of different api node with an edge
    for (ApiNode<Event> apiNode : apiNodeList) {
        // exit boundary events of api node
        List<Event> exitBoundaryEvents = apiNode.getExitApiBoundaryEvents();
        for (Event exitBoundaryEvent : exitBoundaryEvents) {
            List<Event> exitBoundaryEventChildren = graph.getChildrenEvents(exitBoundaryEvent);
            if (exitBoundaryEventChildren != null) {
                for (Event exitBoundaryEventChild : exitBoundaryEventChildren) {
                    // always!
                    if (EnrichedSpanUtils.isEntryApiBoundary(exitBoundaryEventChild)) {
                        // get the api node exit boundary event is connecting to
                        ApiNode<Event> destinationApiNode = entryApiBoundaryEventIdToApiNode.get(exitBoundaryEventChild.getEventId());
                        Optional<ApiNodeEventEdge> edgeBetweenApiNodes = createEdgeBetweenApiNodes(apiNode, destinationApiNode, exitBoundaryEvent, exitBoundaryEventChild);
                        edgeBetweenApiNodes.ifPresent(edge -> {
                            apiNodeEventEdgeList.add(edge);
                            apiExitBoundaryEventIdxWithOutgoingEdge.add(edge.getSrcEventIndex());
                            apiEntryBoundaryEventIdxWithIncomingEdge.add(edge.getTgtEventIndex());
                            apiNodeIdxToEdges.computeIfAbsent(apiNodeHeadEventIdToIndex.get(apiNode.getHeadEvent().getEventId()), v -> Sets.newHashSet()).add(apiNodeEventEdgeList.size() - 1);
                        });
                    } else {
                        if (LOGGER.isDebugEnabled()) {
                            LOGGER.debug("Exit boundary event with eventId: {}, eventName: {}, serviceName: {}," + " can only have entry boundary event as child. Non-entry child:" + " childEventId: {}, childEventName: {}, childServiceName: {}." + " traceId for events: {}", HexUtils.getHex(exitBoundaryEvent.getEventId()), exitBoundaryEvent.getEventName(), exitBoundaryEvent.getServiceName(), HexUtils.getHex(exitBoundaryEventChild.getEventId()), exitBoundaryEventChild.getEventName(), exitBoundaryEventChild.getServiceName(), HexUtils.getHex(trace.getTraceId()));
                        }
                    }
                }
            }
        }
        // Sometimes an exit span might be missing for services like Istio, Kong.
        // Only Entry spans will be populated for these services,
        // an edge must be created between these services as well.
        // 1. get entry boundary event from an api node.
        // 2. find all the children of entry boundary event, which will be entry boundary nodes of
        // different api nodes
        // 3. Check both parent span and child belong to different service as well.
        // 4. connect the entry boundary of different api nodes with an edge.
        Optional<Event> entryBoundaryEvent = apiNode.getEntryApiBoundaryEvent();
        if (entryBoundaryEvent.isPresent()) {
            List<Event> children = graph.getChildrenEvents(entryBoundaryEvent.get());
            if (children != null) {
                for (Event child : children) {
                    // which can happen if exit span missing and both belongs to different services.
                    if (EnrichedSpanUtils.isEntryApiBoundary(child) && EnrichedSpanUtils.areBothSpansFromDifferentService(child, entryBoundaryEvent.get())) {
                        ApiNode<Event> destinationApiNode = entryApiBoundaryEventIdToApiNode.get(child);
                        if (LOGGER.isDebugEnabled()) {
                            LOGGER.debug("Edge between entry boundaries servicename: {} span: {}  to servicename: {} span: {} of trace {}", entryBoundaryEvent.get().getServiceName(), HexUtils.getHex(entryBoundaryEvent.get().getEventId()), child.getServiceName(), HexUtils.getHex(child.getEventId()), HexUtils.getHex(trace.getTraceId()));
                        }
                        Optional<ApiNodeEventEdge> edgeBetweenApiNodes = createEdgeBetweenApiNodes(apiNode, destinationApiNode, entryBoundaryEvent.get(), child);
                        edgeBetweenApiNodes.ifPresent(apiNodeEventEdgeList::add);
                    }
                }
            }
        }
    }
}
Also used : EnrichedSpanUtils(org.hypertrace.traceenricher.enrichedspan.constants.utils.EnrichedSpanUtils) AttributeValue(org.hypertrace.traceenricher.enrichedspan.constants.v1.AttributeValue) AvroBuilderCache.fastNewBuilder(org.hypertrace.core.datamodel.shared.AvroBuilderCache.fastNewBuilder) LoggerFactory(org.slf4j.LoggerFactory) HashBasedTable(com.google.common.collect.HashBasedTable) Edge(org.hypertrace.core.datamodel.Edge) StringUtils(org.apache.commons.lang3.StringUtils) ByteBuffer(java.nio.ByteBuffer) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) StructuredTraceGraph(org.hypertrace.core.datamodel.shared.StructuredTraceGraph) ApiNode(org.hypertrace.core.datamodel.shared.ApiNode) Lists(com.google.common.collect.Lists) Map(java.util.Map) EnrichedSpanConstants(org.hypertrace.traceenricher.enrichedspan.constants.EnrichedSpanConstants) HexUtils(org.hypertrace.core.datamodel.shared.HexUtils) LinkedList(java.util.LinkedList) StructuredTrace(org.hypertrace.core.datamodel.StructuredTrace) Logger(org.slf4j.Logger) ApiNodeEventEdge(org.hypertrace.core.datamodel.ApiNodeEventEdge) Event(org.hypertrace.core.datamodel.Event) Set(java.util.Set) Maps(com.google.common.collect.Maps) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) List(java.util.List) Optional(java.util.Optional) Queue(java.util.Queue) Table(com.google.common.collect.Table) Collections(java.util.Collections) ApiNodeEventEdge(org.hypertrace.core.datamodel.ApiNodeEventEdge) Event(org.hypertrace.core.datamodel.Event)

Example 3 with StructuredTraceGraph

use of org.hypertrace.core.datamodel.shared.StructuredTraceGraph in project hypertrace-ingester by hypertrace.

the class ApiTraceGraph method buildApiTraceGraph.

private void buildApiTraceGraph() {
    StructuredTraceGraph graph = StructuredTraceGraphBuilder.buildGraph(trace);
    buildApiNodes(graph);
    // optimization
    buildApiNodeToIndexMap();
    buildApiNodeEdges(graph);
}
Also used : StructuredTraceGraph(org.hypertrace.core.datamodel.shared.StructuredTraceGraph)

Example 4 with StructuredTraceGraph

use of org.hypertrace.core.datamodel.shared.StructuredTraceGraph in project hypertrace-ingester by hypertrace.

the class StructuredTraceGraphBuilder method buildGraph.

public static StructuredTraceGraph buildGraph(StructuredTrace trace) {
    StructuredTrace cachedTrace = cachedTraceThreadLocal.get();
    StructuredTraceGraph cachedGraph = cachedGraphThreadLocal.get();
    boolean shouldRebuildTraceEventsGraph = GraphBuilderUtil.isTraceEventsChanged(cachedTrace, trace);
    boolean shouldRebuildTraceEntitiesGraph = GraphBuilderUtil.isTraceEntitiesChanged(cachedTrace, trace);
    if (null == cachedGraph || GraphBuilderUtil.isDifferentTrace(cachedTrace, trace) || (shouldRebuildTraceEventsGraph && shouldRebuildTraceEntitiesGraph)) {
        Instant start = Instant.now();
        StructuredTraceGraph graph = new StructuredTraceGraph(trace);
        if (LOG.isDebugEnabled()) {
            LOG.debug("Time taken in building StructuredTraceGraph, duration_millis:{} for tenantId:{}", Duration.between(start, Instant.now()).toMillis(), trace.getCustomerId());
        }
        cachedTraceThreadLocal.set(StructuredTrace.newBuilder(trace).build());
        cachedGraphThreadLocal.set(graph);
        debugGraph("Case: Rebuilding the graph.", graph, trace);
        return graph;
    }
    if (shouldRebuildTraceEventsGraph || shouldRebuildTraceEntitiesGraph) {
        Instant start = Instant.now();
        if (shouldRebuildTraceEventsGraph) {
            cachedGraph.reCreateTraceEventsGraph(trace);
        } else {
            cachedGraph.reCreateTraceEntitiesGraph(trace);
        }
        if (LOG.isDebugEnabled()) {
            LOG.debug("Time taken in building TraceEventsGraph, duration_millis:{} for tenantId:{}", Duration.between(start, Instant.now()).toMillis(), trace.getCustomerId());
        }
        cachedTraceThreadLocal.set(StructuredTrace.newBuilder(trace).build());
        cachedGraphThreadLocal.set(cachedGraph);
        debugGraph("Case: Partially building the graph.", cachedGraph, trace);
        return cachedGraph;
    }
    debugGraph("Case: Not building the graph.", cachedGraphThreadLocal.get(), trace);
    return cachedGraph;
}
Also used : StructuredTrace(org.hypertrace.core.datamodel.StructuredTrace) Instant(java.time.Instant) StructuredTraceGraph(org.hypertrace.core.datamodel.shared.StructuredTraceGraph)

Example 5 with StructuredTraceGraph

use of org.hypertrace.core.datamodel.shared.StructuredTraceGraph in project hypertrace-ingester by hypertrace.

the class StructuredTraceGraphBuilder method debugGraph.

private static void debugGraph(String logPrefix, StructuredTraceGraph graph, StructuredTrace trace) {
    if (null != graph && (null == graph.getTraceEntitiesGraph() || null == graph.getTraceEventsGraph())) {
        LOG.info(logPrefix + "StructuredTraceGraph is not built correctly, trace {}, Is events graph non-null: {}." + " Is entities graph non-null: {}", trace, (null != graph.getTraceEventsGraph()), (null != graph.getTraceEntitiesGraph()));
        // build the graph again and check
        StructuredTraceGraph tempGraph = new StructuredTraceGraph(trace);
        LOG.info(logPrefix + "Recreating StructuredTraceGraph. Is events graph non-null: {}." + " Is entities graph non-null: {}", (null != tempGraph.getTraceEventsGraph()), (null != tempGraph.getTraceEntitiesGraph()));
        tempGraph.reCreateTraceEventsGraph(trace);
        LOG.info(logPrefix + "Recreating events graph. Is events graph non-null: {}." + " Is entities graph non-null: {}", (null != tempGraph.getTraceEventsGraph()), (null != tempGraph.getTraceEntitiesGraph()));
        tempGraph.reCreateTraceEntitiesGraph(trace);
        LOG.info(logPrefix + "Recreating entities graph. Is events graph non-null: {}." + " Is entities graph non-null: {}", (null != tempGraph.getTraceEventsGraph()), (null != tempGraph.getTraceEntitiesGraph()));
    }
}
Also used : StructuredTraceGraph(org.hypertrace.core.datamodel.shared.StructuredTraceGraph)

Aggregations

StructuredTraceGraph (org.hypertrace.core.datamodel.shared.StructuredTraceGraph)15 Event (org.hypertrace.core.datamodel.Event)11 Test (org.junit.jupiter.api.Test)7 List (java.util.List)4 StructuredTrace (org.hypertrace.core.datamodel.StructuredTrace)4 ArrayList (java.util.ArrayList)2 Collections (java.util.Collections)2 HashSet (java.util.HashSet)2 LinkedList (java.util.LinkedList)2 Map (java.util.Map)2 Optional (java.util.Optional)2 StringUtils (org.apache.commons.lang3.StringUtils)2 Pair (org.apache.commons.lang3.tuple.Pair)2 Edge (org.hypertrace.core.datamodel.Edge)2 HexUtils (org.hypertrace.core.datamodel.shared.HexUtils)2 EnrichedSpanConstants (org.hypertrace.traceenricher.enrichedspan.constants.EnrichedSpanConstants)2 EnrichedSpanUtils (org.hypertrace.traceenricher.enrichedspan.constants.utils.EnrichedSpanUtils)2 Logger (org.slf4j.Logger)2 LoggerFactory (org.slf4j.LoggerFactory)2 VisibleForTesting (com.google.common.annotations.VisibleForTesting)1