use of org.hypertrace.core.datamodel.Event 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);
}
}
}
}
}
}
use of org.hypertrace.core.datamodel.Event in project hypertrace-ingester by hypertrace.
the class EnrichedSpanUtilsTest method testGetParent.
@Test
public void testGetParent() {
Event e1 = mock(Event.class);
when(e1.getEventId()).thenReturn(ByteBuffer.wrap("span-1".getBytes()));
Event e2 = mock(Event.class);
when(e2.getEventId()).thenReturn(ByteBuffer.wrap("span-2".getBytes()));
Event e3 = mock(Event.class);
when(e3.getEventId()).thenReturn(ByteBuffer.wrap("span-3".getBytes()));
Event e4 = mock(Event.class);
when(e4.getEventId()).thenReturn(ByteBuffer.wrap("span-4".getBytes()));
Map<ByteBuffer, Event> idToEvent = Map.of(ByteBuffer.wrap("span-1".getBytes()), e1, ByteBuffer.wrap("span-2".getBytes()), e2, ByteBuffer.wrap("span-3".getBytes()), e3, ByteBuffer.wrap("span-4".getBytes()), e4);
Map<ByteBuffer, ByteBuffer> childToParentEventIds = Map.of(ByteBuffer.wrap("span-3".getBytes()), ByteBuffer.wrap("span-2".getBytes()), ByteBuffer.wrap("span-2".getBytes()), ByteBuffer.wrap("span-1".getBytes()), ByteBuffer.wrap("span-4".getBytes()), ByteBuffer.wrap("unknown".getBytes()));
Event parent = SpanAttributeUtils.getParentSpan(e3, childToParentEventIds, idToEvent);
assertEquals(e2, parent);
parent = SpanAttributeUtils.getParentSpan(e2, childToParentEventIds, idToEvent);
assertEquals(e1, parent);
parent = SpanAttributeUtils.getParentSpan(e1, childToParentEventIds, idToEvent);
assertEquals(null, parent);
parent = SpanAttributeUtils.getParentSpan(e4, childToParentEventIds, idToEvent);
assertEquals(null, parent);
}
use of org.hypertrace.core.datamodel.Event in project hypertrace-ingester by hypertrace.
the class EnrichedSpanUtilsTest method should_getHttpMethod.
@Test
public void should_getHttpMethod() {
Event e = createMockEventWithAttribute(RawSpanConstants.getValue(HTTP_METHOD), "GET");
Optional<String> method = EnrichedSpanUtils.getHttpMethod(e);
assertFalse(method.isEmpty());
assertEquals("GET", method.get());
}
use of org.hypertrace.core.datamodel.Event in project hypertrace-ingester by hypertrace.
the class GraphBuilderUtilTest method testIsStructuredTraceChangedForSizeCondition.
@Test
public void testIsStructuredTraceChangedForSizeCondition() {
Entity entity = mock(Entity.class);
Event parent = mock(Event.class);
Event child = mock(Event.class);
Edge eventEdge = mock(Edge.class);
// same size
StructuredTrace cachedTrace = mock(StructuredTrace.class);
when(cachedTrace.getCustomerId()).thenReturn("__defaultTenant");
when(cachedTrace.getTraceId()).thenReturn(ByteBuffer.wrap("2ebbc19b6428510f".getBytes()));
when(cachedTrace.getEntityList()).thenReturn(List.of(entity));
when(cachedTrace.getEventList()).thenReturn(List.of(parent, child));
when(cachedTrace.getEntityEdgeList()).thenReturn(List.of());
when(cachedTrace.getEntityEventEdgeList()).thenReturn(List.of());
when(cachedTrace.getEventEdgeList()).thenReturn(List.of(eventEdge));
StructuredTrace underTestTrace = mock(StructuredTrace.class);
when(underTestTrace.getCustomerId()).thenReturn("__defaultTenant");
when(underTestTrace.getTraceId()).thenReturn(ByteBuffer.wrap("2ebbc19b6428510f".getBytes()));
when(underTestTrace.getEntityList()).thenReturn(List.of(entity));
when(underTestTrace.getEventList()).thenReturn(List.of(parent, child));
when(underTestTrace.getEntityEdgeList()).thenReturn(List.of());
when(underTestTrace.getEntityEventEdgeList()).thenReturn(List.of());
when(underTestTrace.getEventEdgeList()).thenReturn(List.of(eventEdge));
boolean result = GraphBuilderUtil.isStructuredTraceChanged(cachedTrace, underTestTrace);
Assertions.assertFalse(result);
}
use of org.hypertrace.core.datamodel.Event in project hypertrace-ingester by hypertrace.
the class StructuredTraceGraphBuilderTest method testBuildGraph.
@Test
void testBuildGraph() {
Entity entity = mock(Entity.class);
Event parent = mock(Event.class);
Event child = mock(Event.class);
Edge eventEdge = mock(Edge.class);
StructuredTrace underTestTrace = mock(StructuredTrace.class);
when(underTestTrace.getCustomerId()).thenReturn("__defaultTenant");
when(underTestTrace.getTraceId()).thenReturn(ByteBuffer.wrap("2ebbc19b6428510f".getBytes()));
when(underTestTrace.getEntityList()).thenReturn(List.of(entity));
when(underTestTrace.getEventList()).thenReturn(List.of(parent, child));
when(underTestTrace.getEntityEdgeList()).thenReturn(List.of());
when(underTestTrace.getEntityEventEdgeList()).thenReturn(List.of());
when(underTestTrace.getEventEdgeList()).thenReturn(List.of(eventEdge));
try (MockedStatic<StructuredTrace> builderMockedStatic = mockStatic(StructuredTrace.class)) {
StructuredTrace.Builder builder = mock(StructuredTrace.Builder.class);
when(builder.build()).thenReturn(underTestTrace);
builderMockedStatic.when(() -> StructuredTrace.newBuilder(underTestTrace)).thenReturn(builder);
try (MockedConstruction<StructuredTraceGraph> mocked = mockConstruction(StructuredTraceGraph.class)) {
// calls first time
StructuredTraceGraph actual = StructuredTraceGraphBuilder.buildGraph(underTestTrace);
// calls second time, this time it returns from cache
StructuredTraceGraph cached = StructuredTraceGraphBuilder.buildGraph(underTestTrace);
Assertions.assertEquals(actual, cached);
}
}
}
Aggregations