Skip to content

Conversation

@KalinduGandara
Copy link
Contributor

@KalinduGandara KalinduGandara commented Dec 2, 2025

fixes: wso2/product-micro-integrator#4496

Summary by CodeRabbit

  • New Features
    • Added ability to skip main sequence execution per message.
    • Enhanced tracing with error code and error message tracking in OpenTelemetry spans.
    • Introduced mediator-level span filtering to exclude specific mediators from tracing.
    • Added custom properties support for span tagging and statistics collection.
    • Implemented trace filter toggling for improved observability control.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 2, 2025

Walkthrough

This pull request enhances OpenTelemetry support in Apache Synapse with trace filtering capabilities, Axis2 MessageContext integration throughout the telemetry pipeline, custom span properties, and error tracking. Changes span data models, event handlers, span management, and configuration infrastructure to enable fine-grained filtering of telemetry data and enrich span attributes with custom properties.

Changes

Cohort / File(s) Summary
Configuration Constants
modules/core/src/main/java/org/apache/synapse/SynapseConstants.java, modules/core/src/main/java/org/apache/synapse/config/xml/XMLConfigConstants.java, modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/TelemetryConstants.java
Added public constants for skipping main sequence, trace filter XML attributes, and OpenTelemetry error/tag attribute keys and configuration property names.
Trace Filter Infrastructure
modules/core/src/main/java/org/apache/synapse/aspects/AspectConfiguration.java, modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/collectors/RuntimeStatisticCollector.java, modules/core/src/main/java/org/apache/synapse/config/xml/AbstractMediatorFactory.java
Introduced trace filter toggle API in AspectConfiguration, mediator span filtering logic with case-insensitive name matching in RuntimeStatisticCollector, and XML-based configuration support in AbstractMediatorFactory.
Telemetry Event Filtering
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/collectors/OpenEventCollector.java
Enhanced event emission paths to check whether mediators are filtered or tracing is disabled before processing OpenTelemetry events.
Statistics Data Models
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/data/raw/BasicStatisticDataUnit.java, modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/data/raw/StatisticDataUnit.java, modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/data/raw/StatisticsLog.java
Added custom properties map, error code/message fields, and outer-layer span indicator to statistic data units with corresponding accessors.
Event Handler Interfaces
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/event/CloseEventHandler.java, modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/event/OpenEventHandler.java
Added overloaded event handling methods accepting Axis2 MessageContext parameter alongside existing Synapse MessageContext variants.
Axis2 Context Integration
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/span/SpanHandler.java, modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/scoping/TracingScopeManager.java, modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/stores/SpanStore.java
Extended span lifecycle management with Axis2 MessageContext overloads, including tracing scope derivation, span wrapper management, and span finalization support for both Synapse and Axis2 contexts.
Span Enrichment
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/helpers/SpanTagger.java
Added logic to export custom properties from both open and close statistics data units as span attributes, with overload for Axis2 MessageContext.
Message Routing
modules/core/src/main/java/org/apache/synapse/core/axis2/Axis2SynapseEnvironment.java
Introduced guard to conditionally skip main sequence routing when the SynapseConstants.SKIP_MAIN_SEQUENCE property is set on the MessageContext.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Areas requiring extra attention:

  • SpanHandler.java — Contains the densest changes with multiple new private overloads for Axis2 context, transport header propagation, custom tag handling, and outer-level span lifecycle management. Logic flow across synchronized blocks and span store interactions should be carefully validated.
  • RuntimeStatisticCollector.java — Verify case-insensitive filtering logic and initialization sequence for mediator span filter set, especially around TelemetryConstants parsing and debug logging.
  • OpenEventCollector.java — Confirm filtering check is correctly evaluated in all affected code paths (open-entry, child-entry, flow-continuable, flow-splitting, flow-aggregate) without inadvertently suppressing legitimate telemetry.
  • Axis2 context propagation — Ensure all new Axis2 MessageContext overloads in SpanStore, TracingScopeManager, and SpanHandler correctly extract and propagate tracing IDs and statistics identifiers.

Poem

🐰 A filtering feast, with spans now so bright,
Custom tags dance in telemetry's light,
Axis2 contexts flow smooth as can be,
Error codes logged for all eyes to see,
The sequence runs true, no hops left behind! ✨

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is minimal, containing only an issue reference without addressing required template sections like Purpose, Goals, Approach, User stories, Release notes, Documentation, Testing, or Security checks. Complete the PR description using the repository template, including Purpose, Goals, Approach, Release notes, Documentation impact, and Automation tests sections.
Docstring Coverage ⚠️ Warning Docstring coverage is 45.28% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: adding trace filter support, custom header handling, and OpenTelemetry improvements, which align with the substantial modifications across multiple files.
Linked Issues check ✅ Passed The code changes implement OpenTelemetry support enhancements including trace filtering, custom property handling, and Axis2 context integration that address the objective of improving OpenTelemetry support for better tracing capabilities.
Out of Scope Changes check ✅ Passed All changes appear scoped to OpenTelemetry tracing improvements: adding trace filtering, custom span tags, error attributes, and Axis2 MessageContext support for telemetry collection, which align with the linked issue objectives.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (7)
modules/core/src/main/java/org/apache/synapse/config/xml/XMLConfigConstants.java (1)

148-150: LGTM! Consider adding a disable constant for completeness.

The constants follow existing naming conventions. For consistency with TRACE_DISABLE and STATISTICS_DISABLE, you may want to add TRACE_FILTER_DISABLE = "disable" for future use, though this is optional.

modules/core/src/main/java/org/apache/synapse/aspects/AspectConfiguration.java (1)

125-135: Consider adding guard checks for consistency.

The existing enableStatistics() and disableStatistics() methods include guards (if (!statisticsEnable) / if (statisticsEnable)) to avoid redundant assignments. The new trace filter methods don't follow this pattern. While functionally correct, adding guards would maintain consistency.

     public void enableTraceFilter() {
-        this.traceFilterEnable = true;
+        if (!traceFilterEnable) {
+            this.traceFilterEnable = true;
+        }
     }

     public void disableTraceFilter() {
-        this.traceFilterEnable = false;
+        if (traceFilterEnable) {
+            this.traceFilterEnable = false;
+        }
     }
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/helpers/SpanTagger.java (1)

162-241: Axis2 overload has asymmetric feature set compared to Synapse version.

This method omits context property/variable map collection and endpoint attributes present in the Synapse MessageContext overload, but adds error code/message handling (lines 224-232). If this asymmetry is intentional (due to Axis2 context limitations), consider adding the error code/message handling to the Synapse version as well for consistency.

Consider adding error code/message handling to the Synapse MessageContext version:

         if (spanWrapper.getCloseEventStatisticDataUnit() != null) {
             if (spanWrapper.getCloseEventStatisticDataUnit().getCustomProperties() != null) {
                 spanWrapper.getCloseEventStatisticDataUnit().getCustomProperties().forEach(
                         (key, value) -> span.setAttribute(key, String.valueOf(value))
                 );
             }
+            if (spanWrapper.getCloseEventStatisticDataUnit().getErrorCode() != null) {
+                span.setAttribute(TelemetryConstants.ERROR_CODE_ATTRIBUTE_KEY,
+                        spanWrapper.getCloseEventStatisticDataUnit().getErrorCode());
+            }
+            if (spanWrapper.getCloseEventStatisticDataUnit().getErrorMessage() != null) {
+                span.setAttribute(TelemetryConstants.ERROR_MESSAGE_ATTRIBUTE_KEY,
+                        spanWrapper.getCloseEventStatisticDataUnit().getErrorMessage());
+            }
         }
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/scoping/TracingScopeManager.java (1)

62-82: Consider null-safety for tracingScopeId.

The Axis2 overload correctly mirrors the Synapse version. However, if FLOW_STATISTICS_ID is not set on the MessageContext, extractTracingScopeId returns null, which could lead to storing/retrieving scopes with a null key.

Consider adding a null check:

     public TracingScope getTracingScope(org.apache.axis2.context.MessageContext msgCtx) {
         synchronized (tracingScopes) {
             String tracingScopeId = extractTracingScopeId(msgCtx);
+            if (tracingScopeId == null) {
+                return null; // or throw an exception/log a warning
+            }
             if (tracingScopes.containsKey(tracingScopeId)) {

This would also be beneficial for the existing Synapse MessageContext overload.

modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/TelemetryConstants.java (1)

91-93: Consider using OTEL prefix instead of OLTP.

The constants use OLTP prefix (e.g., oltp.custom.span.header.tags), but OpenTelemetry is typically abbreviated as OTEL. Unless OLTP is an established convention in this codebase, consider renaming for consistency with OpenTelemetry naming conventions:

-    public static final String OLTP_CUSTOM_SPAN_TAGS = "oltp.custom.span.header.tags";
+    public static final String OTEL_CUSTOM_SPAN_TAGS = "otel.custom.span.header.tags";

-    public static final String OLTP_FILTERED_MEDIATOR_NAMES = "oltp.filtered.mediator.names";
+    public static final String OTEL_FILTERED_MEDIATOR_NAMES = "otel.filtered.mediator.names";
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/event/CloseEventHandler.java (1)

51-58: Consider adding missing Axis2 overloads for completeness.

The interface adds Axis2 overloads for handleCloseEntryEvent, handleCloseFlowForcefully, and handleCloseEntryWithErrorEvent, but not for handleTryEndFlow and handleScatterGatherFinishEvent. If Axis2 context support is needed for those operations in the future, this inconsistency may cause issues.

Verify whether handleTryEndFlow and handleScatterGatherFinishEvent need Axis2 overloads for complete Dataservices OpenTelemetry support.

Also applies to: 81-88

modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/span/SpanHandler.java (1)

252-279: Significant code duplication in custom span tags logic.

The custom span tags extraction logic is duplicated between the Synapse startSpan (lines 255-279) and Axis2 startSpan (lines 355-378). Consider extracting to a shared helper method.

Extract to a private helper method:

private void extractAndSetCustomSpanTags(Map headersMap, StatisticDataUnit statisticDataUnit, 
                                          Object msgContext, boolean isSynapseContext) {
    Object prevCustomSpanTagsObj = isSynapseContext 
        ? ((MessageContext) msgContext).getProperty(TelemetryConstants.OLTP_CUSTOM_SPAN_TAGS)
        : ((org.apache.axis2.context.MessageContext) msgContext).getProperty(TelemetryConstants.OLTP_CUSTOM_SPAN_TAGS);
    // ... rest of shared logic
}

Also applies to: 355-378

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2b10bd4 and 064637b.

📒 Files selected for processing (17)
  • modules/core/src/main/java/org/apache/synapse/SynapseConstants.java (1 hunks)
  • modules/core/src/main/java/org/apache/synapse/aspects/AspectConfiguration.java (2 hunks)
  • modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/collectors/OpenEventCollector.java (5 hunks)
  • modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/collectors/RuntimeStatisticCollector.java (5 hunks)
  • modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/data/raw/BasicStatisticDataUnit.java (3 hunks)
  • modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/data/raw/StatisticDataUnit.java (3 hunks)
  • modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/data/raw/StatisticsLog.java (3 hunks)
  • modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/TelemetryConstants.java (1 hunks)
  • modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/event/CloseEventHandler.java (2 hunks)
  • modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/event/OpenEventHandler.java (1 hunks)
  • modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/span/SpanHandler.java (11 hunks)
  • modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/helpers/SpanTagger.java (1 hunks)
  • modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/scoping/TracingScopeManager.java (2 hunks)
  • modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/stores/SpanStore.java (3 hunks)
  • modules/core/src/main/java/org/apache/synapse/config/xml/AbstractMediatorFactory.java (1 hunks)
  • modules/core/src/main/java/org/apache/synapse/config/xml/XMLConfigConstants.java (1 hunks)
  • modules/core/src/main/java/org/apache/synapse/core/axis2/Axis2SynapseEnvironment.java (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/helpers/SpanTagger.java (2)
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/OpenTelemetryManagerHolder.java (1)
  • OpenTelemetryManagerHolder (31-87)
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/TelemetryConstants.java (1)
  • TelemetryConstants (21-94)
modules/core/src/main/java/org/apache/synapse/core/axis2/Axis2SynapseEnvironment.java (1)
modules/core/src/main/java/org/apache/synapse/SynapseConstants.java (1)
  • SynapseConstants (30-745)
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/stores/SpanStore.java (2)
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/helpers/TracingUtils.java (1)
  • TracingUtils (28-65)
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/helpers/SpanTagger.java (1)
  • SpanTagger (33-242)
modules/core/src/main/java/org/apache/synapse/config/xml/AbstractMediatorFactory.java (1)
modules/core/src/main/java/org/apache/synapse/config/xml/XMLConfigConstants.java (1)
  • XMLConfigConstants (30-151)
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/span/SpanHandler.java (3)
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/TelemetryConstants.java (1)
  • TelemetryConstants (21-94)
modules/core/src/main/java/org/apache/synapse/config/SynapsePropertiesLoader.java (1)
  • SynapsePropertiesLoader (32-119)
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/helpers/TracingUtils.java (1)
  • TracingUtils (28-65)
🔇 Additional comments (18)
modules/core/src/main/java/org/apache/synapse/config/xml/AbstractMediatorFactory.java (1)

186-196: LGTM! Trace filter attribute handling follows existing patterns.

The implementation correctly mirrors the existing patterns for trace and statistics attribute handling, maintaining consistency in the codebase.

modules/core/src/main/java/org/apache/synapse/SynapseConstants.java (1)

743-744: LGTM!

The new constant follows existing naming conventions and is appropriately placed with related constants.

modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/data/raw/StatisticsLog.java (1)

173-174: LGTM!

The customProperties field follows the existing pattern for other map fields like contextPropertyMap and transportPropertyMap, with proper initialization in the constructor and a getter method.

Also applies to: 206-206, 434-437

modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/collectors/OpenEventCollector.java (3)

105-110: LGTM! Filtering logic is correctly applied.

The trace filtering logic properly skips OpenTelemetry handling when the mediator is in the filtered list or when trace filtering is explicitly enabled on the component.


139-144: Consistent filtering applied across event methods.

The filtering logic is consistently applied across reportChildEntryEvent, reportFlowContinuableEvent, reportFlowSplittingEvent, and reportFlowAggregateEvent, maintaining uniform behavior for trace filtering.

Also applies to: 175-180, 212-217, 248-253


266-281: Verify: reportFlowAsynchronousEvent lacks trace filtering.

Unlike other event reporting methods in this class, reportFlowAsynchronousEvent does not include an isFiltered check before calling the OpenTelemetry handler. Confirm whether this omission is intentional for asynchronous events or represents an inconsistency that should be addressed.

modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/data/raw/BasicStatisticDataUnit.java (1)

71-75: LGTM! The new customProperties field follows existing patterns.

The addition of customProperties with getter/setter is consistent with other fields in this data carrier class (e.g., elasticMetadata, messageContext). The field appropriately allows null values and follows the same mutable reference pattern used throughout the class.

Also applies to: 139-146

modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/helpers/SpanTagger.java (1)

140-152: LGTM! Custom properties propagation for Synapse MessageContext.

The addition correctly exports custom properties from both open and close event data units as span attributes, ensuring complete property propagation.

modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/collectors/RuntimeStatisticCollector.java (3)

145-159: LGTM! Mediator span filter initialization is well-implemented.

The initialization correctly:

  • Guards against null/empty configuration values
  • Uses stream API for clean parsing
  • Normalizes to lowercase for case-insensitive matching
  • Logs the filter list at debug level

181-193: LGTM! Axis2 MessageContext overload provides necessary compatibility.

The method correctly mirrors the Synapse MessageContext version for setting trace IDs in Axis2 contexts.


286-297: LGTM! Filter check is correctly implemented.

The method safely handles:

  • Null componentName via early check
  • Component names without colons (split(":")[0] returns original string)
  • Case-insensitive matching via lowercase normalization
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/scoping/TracingScopeManager.java (1)

94-102: LGTM! Axis2 context ID extraction is consistent with existing pattern.

The overloaded method correctly extracts the tracing scope ID from the Axis2 MessageContext using the same property key.

modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/event/OpenEventHandler.java (1)

37-43: Interface extension requires implementations to be updated.

The new Axis2 MessageContext overload is appropriate for enabling Axis2-based tracing. Verify that all classes implementing OpenEventHandler have been updated to implement this new method signature.

modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/TelemetryConstants.java (1)

85-86: LGTM!

The error attribute constants follow OpenTelemetry semantic conventions for error tracking (error.code, error.message).

modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/event/CloseEventHandler.java (1)

35-42: LGTM!

The new Axis2 MessageContext overloads maintain consistency with existing method signatures and Javadoc style.

modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/data/raw/StatisticDataUnit.java (2)

82-86: LGTM!

The new fields (componentTypeString, errorCode, errorMessage, isOuterLayerSpan) are well-structured and follow the existing patterns in the class. Default initialization for isOuterLayerSpan = false is appropriate.

Also applies to: 134-144


319-350: LGTM!

The new accessor methods follow JavaBean conventions and are consistent with the existing codebase style.

modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/span/SpanHandler.java (1)

568-585: Both finishSpan overloads have identical logic in the outer-level span handling block.

The Synapse and Axis2 versions (lines 554–567 and 568–585, respectively) both execute the same code path in their else blocks: spanStore.finishSpan() followed by tracingScopeManager.cleanupTracingScope(). There is no difference in how outer-level spans are finished between the two overloads. Neither method contains calls to isEventCollectionFinished or cleanupContinuationStateSequences — these methods do not exist in this class.

Likely an incorrect or invalid review comment.

Comment on lines +267 to +272
String[] customTags = customTagsString.split(",");
Map<String, Object> customTagsMap = new HashMap<>();
for (String tag : customTags) {
if (headersMap.containsKey(tag.trim())) {
customTagsMap.put(tag, headersMap.get(tag));
}
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

Inconsistent key handling in custom tags map.

In the Synapse version (line 271), the key is stored with the original (potentially untrimmed) value, but the header lookup uses tag.trim(). In the Axis2 version (line 370), the same pattern exists. This may cause issues if the configured tag has leading/trailing whitespace.

                     for (String tag : customTags) {
-                        if (headersMap.containsKey(tag.trim())) {
-                            customTagsMap.put(tag, headersMap.get(tag));
+                        String trimmedTag = tag.trim();
+                        if (headersMap.containsKey(trimmedTag)) {
+                            customTagsMap.put(trimmedTag, headersMap.get(trimmedTag));
                         }
                     }

Also applies to: 365-371

🤖 Prompt for AI Agents
In
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/span/SpanHandler.java
around lines 267-272 (and similarly around 365-371), the code trims the tag when
looking up headers but uses the untrimmed original tag as the map key, which can
cause mismatched keys when configured tags have surrounding whitespace; update
the logic to trim the tag once into a local variable (e.g., String key =
tag.trim()), use that trimmed key for the headersMap lookup and also as the key
when putting into customTagsMap so both lookup and storage are consistent.

}
}

statisticDataUnit.setTransportHeaderMap(headersMap);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Remove redundant setTransportHeaderMap call.

statisticDataUnit.setTransportHeaderMap(headersMap) is already called at line 352. This duplicate call at line 381 is unnecessary.

-        statisticDataUnit.setTransportHeaderMap(headersMap);
-
         String spanId = TracingUtils.extractId(statisticDataUnit);
📝 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
statisticDataUnit.setTransportHeaderMap(headersMap);
🤖 Prompt for AI Agents
In
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/span/SpanHandler.java
around line 381, there is a redundant call to
statisticDataUnit.setTransportHeaderMap(headersMap) (it was already set at line
352); remove the duplicate call at line 381 so the transport header map is only
assigned once, leaving the earlier assignment intact.

Comment on lines +474 to +490
@Override
public void handleCloseFlowForcefully(BasicStatisticDataUnit basicStatisticDataUnit,
org.apache.axis2.context.MessageContext msgCtx) {
TracingScope tracingScope = tracingScopeManager.getTracingScope(msgCtx);
SpanStore spanStore = tracingScope.getSpanStore();
String spanWrapperId = TracingUtils.extractId(basicStatisticDataUnit);
SpanWrapper spanWrapper = spanStore.getSpanWrapper(spanWrapperId);

// finish the current span
handleCloseEvent(basicStatisticDataUnit, msgCtx, true);

// finish outer level spans since the control is not returned to the original flow to close them gracefully.
while (spanWrapper.getParentSpanWrapper() != null) {
spanWrapper = spanWrapper.getParentSpanWrapper();
spanStore.finishSpan(spanWrapper, msgCtx, true);
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Inconsistent error flag behavior between Synapse and Axis2 overloads.

The Axis2 handleCloseFlowForcefully always calls handleCloseEvent with isError=true (line 483) and finishes parent spans with isError=true (line 488), whereas the Synapse version uses isError=false (line 465). This behavioral difference may cause inconsistent span status reporting.

         // finish the current span
-        handleCloseEvent(basicStatisticDataUnit, msgCtx, true);
+        handleCloseEvent(basicStatisticDataUnit, msgCtx, false);

         // finish outer level spans since the control is not returned to the original flow to close them gracefully.
         while (spanWrapper.getParentSpanWrapper() != null) {
             spanWrapper = spanWrapper.getParentSpanWrapper();
-            spanStore.finishSpan(spanWrapper, msgCtx, true);
+            spanStore.finishSpan(spanWrapper, msgCtx);
         }

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/span/SpanHandler.java
around lines 474 to 490: the Axis2 overload incorrectly marks the close flow as
an error by passing isError=true to handleCloseEvent and to spanStore.finishSpan
for parent spans, creating inconsistent span status versus the Synapse overload
which uses isError=false; change the calls to use isError=false (or otherwise
mirror the Synapse overload behavior) so
handleCloseEvent(basicStatisticDataUnit, msgCtx, false) is called and
spanStore.finishSpan(spanWrapper, msgCtx, false) is used in the parent loop,
ensuring consistent non-error closure semantics.

Comment on lines +479 to +489
String spanWrapperId = TracingUtils.extractId(basicStatisticDataUnit);
SpanWrapper spanWrapper = spanStore.getSpanWrapper(spanWrapperId);

// finish the current span
handleCloseEvent(basicStatisticDataUnit, msgCtx, true);

// finish outer level spans since the control is not returned to the original flow to close them gracefully.
while (spanWrapper.getParentSpanWrapper() != null) {
spanWrapper = spanWrapper.getParentSpanWrapper();
spanStore.finishSpan(spanWrapper, msgCtx, true);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Potential NullPointerException in parent span traversal.

If spanStore.getSpanWrapper(spanWrapperId) returns null, the while loop at line 486 will throw a NullPointerException. The Synapse version at line 468 has the same risk.

Add a null check before traversing:

         SpanWrapper spanWrapper = spanStore.getSpanWrapper(spanWrapperId);

         // finish the current span
         handleCloseEvent(basicStatisticDataUnit, msgCtx, true);

         // finish outer level spans since the control is not returned to the original flow to close them gracefully.
-        while (spanWrapper.getParentSpanWrapper() != null) {
+        while (spanWrapper != null && spanWrapper.getParentSpanWrapper() != null) {
             spanWrapper = spanWrapper.getParentSpanWrapper();
             spanStore.finishSpan(spanWrapper, msgCtx, true);
         }
🤖 Prompt for AI Agents
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/management/handling/span/SpanHandler.java
around lines 479-489: spanStore.getSpanWrapper(spanWrapperId) may return null
and the subsequent while (spanWrapper.getParentSpanWrapper() != null) will NPE;
add a null check after retrieving spanWrapper and only call handleCloseEvent and
traverse parentSpanWrapper/finishSpan if spanWrapper != null (log a warning or
return early if null) to avoid the NullPointerException.

Comment on lines +126 to +140
public SpanWrapper addSpanWrapper(String spanId,
Span activeSpan,
StatisticDataUnit statisticDataUnit,
SpanWrapper parentSpanWrapper,
org.apache.axis2.context.MessageContext msgCtx) {
SpanWrapper spanWrapper = new SpanWrapper(spanId, activeSpan, statisticDataUnit, parentSpanWrapper);
spanWrappers.put(spanId, spanWrapper);
spanWrapper.addKnownSynCtxHashCodeToAllParents(TracingUtils.getSystemIdentityHashCode(msgCtx));
if (parentSpanWrapper != null) {
parentSpanWrapper.addChildComponentUniqueId(statisticDataUnit.getComponentId());
}
componentUniqueIdWiseSpanWrappers.put(statisticDataUnit.getComponentId(), spanWrapper);
activeSpanWrappers.add(spanWrapper);
return spanWrapper;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Missing anonymous sequence handling in Axis2 overload.

The Axis2 addSpanWrapper overload is missing the anonymous sequence handling present in the Synapse MessageContext version (lines 103-108). This could lead to incorrect span parent relationships when anonymous sequences are involved in Axis2 contexts.

Apply this diff to add the missing logic:

     public SpanWrapper addSpanWrapper(String spanId,
                                       Span activeSpan,
                                       StatisticDataUnit statisticDataUnit,
                                       SpanWrapper parentSpanWrapper,
                                       org.apache.axis2.context.MessageContext msgCtx) {
         SpanWrapper spanWrapper = new SpanWrapper(spanId, activeSpan, statisticDataUnit, parentSpanWrapper);
         spanWrappers.put(spanId, spanWrapper);
         spanWrapper.addKnownSynCtxHashCodeToAllParents(TracingUtils.getSystemIdentityHashCode(msgCtx));
         if (parentSpanWrapper != null) {
             parentSpanWrapper.addChildComponentUniqueId(statisticDataUnit.getComponentId());
+            if (TracingUtils.isAnonymousSequence(spanWrapper.getStatisticDataUnit())) {
+                /*
+                Add this anonymous sequence to the parent.
+                Note that, anonymous sequences are not pushed to the continuation stack
+                */
+                parentSpanWrapper.addAnonymousSequence(spanId, spanWrapper);
+            }
         }
         componentUniqueIdWiseSpanWrappers.put(statisticDataUnit.getComponentId(), spanWrapper);
         activeSpanWrappers.add(spanWrapper);
         return spanWrapper;
     }
📝 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
public SpanWrapper addSpanWrapper(String spanId,
Span activeSpan,
StatisticDataUnit statisticDataUnit,
SpanWrapper parentSpanWrapper,
org.apache.axis2.context.MessageContext msgCtx) {
SpanWrapper spanWrapper = new SpanWrapper(spanId, activeSpan, statisticDataUnit, parentSpanWrapper);
spanWrappers.put(spanId, spanWrapper);
spanWrapper.addKnownSynCtxHashCodeToAllParents(TracingUtils.getSystemIdentityHashCode(msgCtx));
if (parentSpanWrapper != null) {
parentSpanWrapper.addChildComponentUniqueId(statisticDataUnit.getComponentId());
}
componentUniqueIdWiseSpanWrappers.put(statisticDataUnit.getComponentId(), spanWrapper);
activeSpanWrappers.add(spanWrapper);
return spanWrapper;
}
public SpanWrapper addSpanWrapper(String spanId,
Span activeSpan,
StatisticDataUnit statisticDataUnit,
SpanWrapper parentSpanWrapper,
org.apache.axis2.context.MessageContext msgCtx) {
SpanWrapper spanWrapper = new SpanWrapper(spanId, activeSpan, statisticDataUnit, parentSpanWrapper);
spanWrappers.put(spanId, spanWrapper);
spanWrapper.addKnownSynCtxHashCodeToAllParents(TracingUtils.getSystemIdentityHashCode(msgCtx));
if (parentSpanWrapper != null) {
parentSpanWrapper.addChildComponentUniqueId(statisticDataUnit.getComponentId());
if (TracingUtils.isAnonymousSequence(spanWrapper.getStatisticDataUnit())) {
/*
Add this anonymous sequence to the parent.
Note that, anonymous sequences are not pushed to the continuation stack
*/
parentSpanWrapper.addAnonymousSequence(spanId, spanWrapper);
}
}
componentUniqueIdWiseSpanWrappers.put(statisticDataUnit.getComponentId(), spanWrapper);
activeSpanWrappers.add(spanWrapper);
return spanWrapper;
}
🤖 Prompt for AI Agents
In
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/stores/SpanStore.java
around lines 126-140, the Axis2 overload of addSpanWrapper is missing the
anonymous-sequence handling that exists in the Synapse MessageContext overload
(lines ~103-108); update this method to mirror that logic: after creating and
putting the new SpanWrapper, detect if the current statisticDataUnit/msgCtx
represents an anonymous sequence (use the same check/constants used in the
MessageContext overload), and if so resolve the actual parent span wrapper for
the anonymous sequence (lookup by the anonymous sequence component id in
componentUniqueIdWiseSpanWrappers or via the same TracingUtils helper) and
attach the new span as a child of that resolved parent (call the same
addChildComponentUniqueId / parent linking method used in the other overload).
Ensure you still populate componentUniqueIdWiseSpanWrappers and
activeSpanWrappers exactly as before, but with the additional anonymous-sequence
parent resolution and parent linking inserted in the same place relative to
those operations as in the MessageContext version.

Comment on lines +183 to +202
/**
* Denotes the end of a span.
* Adds tags to the span and removes reference to the appropriate span wrapper in activeSpanWrappers.
*
* @param spanWrapper Span wrapper object, which has been already created
* @param msgCtx Synapse message context
* @param isError finishing the span with an error
*/
public void finishSpan(SpanWrapper spanWrapper, org.apache.axis2.context.MessageContext msgCtx, boolean isError) {
if (spanWrapper != null && spanWrapper.getSpan() != null) {
if (spanWrapper.getStatisticDataUnit() != null) {
SpanTagger.setSpanTags(spanWrapper, msgCtx);
}
if (isError) {
spanWrapper.getSpan().setStatus(StatusCode.ERROR);
}
spanWrapper.getSpan().end();
activeSpanWrappers.remove(spanWrapper);
}
}
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

Fix Javadoc comment: incorrect parameter description.

The Javadoc states @param msgCtx Synapse message context but the parameter is actually an Axis2 MessageContext.

     /**
      * Denotes the end of a span.
      * Adds tags to the span and removes reference to the appropriate span wrapper in activeSpanWrappers.
      *
      * @param spanWrapper Span wrapper object, which has been already created
-     * @param msgCtx      Synapse message context
+     * @param msgCtx      Axis2 message context
      * @param isError     finishing the span with an error
      */
🤖 Prompt for AI Agents
modules/core/src/main/java/org/apache/synapse/aspects/flow/statistics/tracing/opentelemetry/stores/SpanStore.java
around lines 183 to 202: the Javadoc for finishSpan incorrectly describes the
msgCtx parameter as a "Synapse message context"; update the @param tag to
correctly state that msgCtx is an Axis2 MessageContext (e.g., "Axis2
MessageContext" or "org.apache.axis2.context.MessageContext") and ensure wording
matches the method signature and imports.

Comment on lines +361 to +364
Object skipMainSequenceObj = synCtx.getProperty(SynapseConstants.SKIP_MAIN_SEQUENCE);
if (skipMainSequenceObj != null && (Boolean) skipMainSequenceObj) {
return true;
}
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 ClassCastException with unsafe cast.

The direct cast to Boolean will throw a ClassCastException if the property is set as a non-Boolean type (e.g., String "true"). Consider using Boolean.TRUE.equals() for safer comparison.

-                    Object skipMainSequenceObj = synCtx.getProperty(SynapseConstants.SKIP_MAIN_SEQUENCE);
-                    if (skipMainSequenceObj != null && (Boolean) skipMainSequenceObj) {
+                    Object skipMainSequenceObj = synCtx.getProperty(SynapseConstants.SKIP_MAIN_SEQUENCE);
+                    if (Boolean.TRUE.equals(skipMainSequenceObj)) {
                         return true;
                     }
📝 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
Object skipMainSequenceObj = synCtx.getProperty(SynapseConstants.SKIP_MAIN_SEQUENCE);
if (skipMainSequenceObj != null && (Boolean) skipMainSequenceObj) {
return true;
}
Object skipMainSequenceObj = synCtx.getProperty(SynapseConstants.SKIP_MAIN_SEQUENCE);
if (Boolean.TRUE.equals(skipMainSequenceObj)) {
return true;
}
🤖 Prompt for AI Agents
In
modules/core/src/main/java/org/apache/synapse/core/axis2/Axis2SynapseEnvironment.java
around lines 361 to 364, the code unsafely casts
synCtx.getProperty(SynapseConstants.SKIP_MAIN_SEQUENCE) to Boolean which can
throw ClassCastException if the property is a non-Boolean (e.g., String);
replace the direct cast with a safe check such as
Boolean.TRUE.equals(skipMainSequenceObj) or explicitly handle String values
(e.g., parse "true"/"false") so the condition only returns true when the
property semantically represents true without throwing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Adding OpenTelemetry support on Dataservices

1 participant