Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import org.apache.synapse.aspects.flow.statistics.util.StatisticDataCollectionHelper;
import org.apache.synapse.aspects.flow.statistics.util.StatisticsConstants;

import java.util.Objects;

/**
* CloseEventCollector receives close statistic events from synapse mediation engine. It Receives Statistics for
* Proxy Services, Inbound Endpoint, APIs, Sequences, Endpoints, Mediators and Resources.
Expand All @@ -50,7 +52,7 @@ public class CloseEventCollector extends RuntimeStatisticCollector {
*/
public static void closeEntryEvent(MessageContext messageContext, String componentName, ComponentType componentType,
Integer currentIndex, boolean isContentAltering) {
closeEntryEvent(messageContext, componentName, componentType, currentIndex, isContentAltering, null, false);
closeEntryEvent(messageContext, componentName, componentType, currentIndex, isContentAltering, null, false);
}

/**
Expand Down Expand Up @@ -121,6 +123,12 @@ public static void closeEntryEvent(MessageContext messageContext, String compone
} else {
OpenTelemetryManagerHolder.getOpenTelemetryManager().getHandler().
handleCloseEntryEvent(statisticDataUnit, messageContext);

// Set SKIP_CHILD_EVENTS property to false at the end of connector operation span.
if (componentType == ComponentType.MEDIATOR && Objects.equals(componentName, "InvokeMediator:Connector")) {
messageContext.setProperty(StatisticsConstants.SKIP_CHILD_EVENTS, false);

}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import org.apache.synapse.aspects.flow.statistics.util.StatisticDataCollectionHelper;
import org.apache.synapse.aspects.flow.statistics.util.StatisticsConstants;

import java.util.Objects;

/**
* OpenEventCollector receives open statistic events from synapse mediation engine. It Receives Statistics for Proxy
* Services, Inbound Endpoints, APIs, Sequences, Endpoints, Mediators and Resources.
Expand Down Expand Up @@ -61,6 +63,11 @@ public static Integer reportEntryEvent(MessageContext messageContext, String com
boolean isCollectingTracing = (isCollectingProperties() || isCollectingPayloads() || isCollectingVariables())
&& aspectConfiguration != null && aspectConfiguration.isTracingEnabled();

// Purpose : Set this property to true where you want to skip creating spans for child entries
if (messageContext.getProperty(StatisticsConstants.SKIP_CHILD_EVENTS) == null) {
messageContext.setProperty(StatisticsConstants.SKIP_CHILD_EVENTS, false);
}

Boolean isFlowStatisticEnabled =
(Boolean) messageContext.getProperty(StatisticsConstants.FLOW_STATISTICS_IS_COLLECTED);//todo try to use single object for "FLOW_TRACE_IS_COLLECTED"
if (isCollectingStatistics) {
Expand Down Expand Up @@ -103,9 +110,10 @@ public static Integer reportEntryEvent(MessageContext messageContext, String com
addEventAndIncrementCount(messageContext, openEvent);

boolean isFiltered = isSpanFilteredMediator(componentName, aspectConfiguration);
if (!isFiltered && isOpenTelemetryEnabled()) {
OpenTelemetryManagerHolder.getOpenTelemetryManager().getHandler()
.handleOpenEntryEvent(statisticDataUnit, messageContext);
if (!isFiltered && isOpenTelemetryEnabled()
&& messageContext.getProperty(StatisticsConstants.SKIP_CHILD_EVENTS).equals(false)) {
OpenTelemetryManagerHolder.getOpenTelemetryManager().getHandler()
.handleOpenEntryEvent(statisticDataUnit, messageContext);
}
Comment on lines +113 to 117
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential NPE if SKIP_CHILD_EVENTS is unexpectedly null.

Line 114 calls .equals(false) directly on the property value without a null check. While the initialization at lines 67-69 should prevent this in normal flows, the pattern differs from the safer null-checks used in reportChildEntryEvent and reportFlowContinuableEvent.

🔎 Proposed fix for consistency
             boolean isFiltered = isSpanFilteredMediator(componentName, aspectConfiguration);
-            if (!isFiltered && isOpenTelemetryEnabled()
-                    && messageContext.getProperty(StatisticsConstants.SKIP_CHILD_EVENTS).equals(false)) {
+            boolean skipChildEvents = Boolean.TRUE.equals(
+                    messageContext.getProperty(StatisticsConstants.SKIP_CHILD_EVENTS));
+            if (!isFiltered && isOpenTelemetryEnabled() && !skipChildEvents) {
                 OpenTelemetryManagerHolder.getOpenTelemetryManager().getHandler()
                             .handleOpenEntryEvent(statisticDataUnit, messageContext);
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (!isFiltered && isOpenTelemetryEnabled()
&& messageContext.getProperty(StatisticsConstants.SKIP_CHILD_EVENTS).equals(false)) {
OpenTelemetryManagerHolder.getOpenTelemetryManager().getHandler()
.handleOpenEntryEvent(statisticDataUnit, messageContext);
}
boolean isFiltered = isSpanFilteredMediator(componentName, aspectConfiguration);
boolean skipChildEvents = Boolean.TRUE.equals(
messageContext.getProperty(StatisticsConstants.SKIP_CHILD_EVENTS));
if (!isFiltered && isOpenTelemetryEnabled() && !skipChildEvents) {
OpenTelemetryManagerHolder.getOpenTelemetryManager().getHandler()
.handleOpenEntryEvent(statisticDataUnit, messageContext);
}
🤖 Prompt for AI Agents
In
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/collectors/OpenEventCollector.java
around lines 113 to 117, the condition calls
messageContext.getProperty(StatisticsConstants.SKIP_CHILD_EVENTS).equals(false)
which can NPE if the property is null; change the check to use a null-safe
Boolean comparison (e.g.,
Boolean.FALSE.equals(messageContext.getProperty(StatisticsConstants.SKIP_CHILD_EVENTS)))
or explicitly test for null before equals so the overall if remains: if
(!isFiltered && isOpenTelemetryEnabled() &&
Boolean.FALSE.equals(messageContext.getProperty(StatisticsConstants.SKIP_CHILD_EVENTS)))
then call handleOpenEntryEvent, matching the null-safety used in
reportChildEntryEvent and reportFlowContinuableEvent.


return statisticDataUnit.getCurrentIndex();
Expand Down Expand Up @@ -136,9 +144,11 @@ public static Integer reportChildEntryEvent(MessageContext messageContext, Strin
aspectConfiguration);

boolean isFiltered = isSpanFilteredMediator(componentName, aspectConfiguration);
if (!isFiltered && isOpenTelemetryEnabled()) {
OpenTelemetryManagerHolder.getOpenTelemetryManager().getHandler()
.handleOpenChildEntryEvent(statisticDataUnit, messageContext);
boolean skipChildEvents = messageContext.getProperty(StatisticsConstants.SKIP_CHILD_EVENTS) != null &&
messageContext.getProperty(StatisticsConstants.SKIP_CHILD_EVENTS).equals(true);
if (!isFiltered && isOpenTelemetryEnabled() && !skipChildEvents) {
OpenTelemetryManagerHolder.getOpenTelemetryManager().getHandler()
.handleOpenChildEntryEvent(statisticDataUnit, messageContext);
}

return statisticDataUnit.getCurrentIndex();
Expand Down Expand Up @@ -171,11 +181,19 @@ public static Integer reportFlowContinuableEvent(MessageContext messageContext,
aspectConfiguration);

boolean isFiltered = isSpanFilteredMediator(componentName, aspectConfiguration);
if (!isFiltered && isOpenTelemetryEnabled()) {
OpenTelemetryManagerHolder.getOpenTelemetryManager().getHandler()
.handleOpenFlowContinuableEvent(statisticDataUnit, messageContext);
boolean skipChildEvents = messageContext.getProperty(StatisticsConstants.SKIP_CHILD_EVENTS) != null &&
messageContext.getProperty(StatisticsConstants.SKIP_CHILD_EVENTS).equals(true);
if (!isFiltered && isOpenTelemetryEnabled() && !skipChildEvents) {
OpenTelemetryManagerHolder.getOpenTelemetryManager().getHandler()
.handleOpenFlowContinuableEvent(statisticDataUnit, messageContext);
}

// Special case to skip child events for connectors where connector operation will be shown as a single unit
// in the tracing span.
if (componentType == ComponentType.MEDIATOR && Objects.equals(componentName, "InvokeMediator:Connector")) {
messageContext.setProperty(StatisticsConstants.SKIP_CHILD_EVENTS, true);
}

return statisticDataUnit.getCurrentIndex();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,4 +199,6 @@ public static String getComponentTypeToString(ComponentType componentType) {
public static final String QUEUE_EVICTION_POLICY_OLD_MESSAGES = "old-messages-first";

public static final String QUEUE_EVICTION_POLICY_NEW_MESSAGES = "new-messages-first";

public static final String SKIP_CHILD_EVENTS = "SKIP_CHILD_EVENTS";
}
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ public void setCommentsList(List<String> commentsList) {
* Returns the name of the class of respective mediator. This was introduced to provide a unique way to get the
* mediator name because getType is implemented in different ways in different mediators (e.g.
* PayloadFactoryMediator)
* @return
* @return the name of the mediator
*/
public String getMediatorName(){
String cls = getClass().getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,12 @@ private boolean isContentAware(InvokeParam param) {
return false;
}

@Override
public String getMediatorName() {
// This is to differentiate between connectors and template mediators in open-telemetry.
return super.getMediatorName() + (isDynamicMediator() ? ":Connector" : ":Template");
}

public boolean mediate(MessageContext synCtx, ContinuationState continuationState) {
SynapseLog synLog = getLog(synCtx);

Expand Down
Loading