Skip to content

Conversation

@aka4rKO
Copy link

@aka4rKO aka4rKO commented Nov 26, 2025

Purpose

$subject

Summary by CodeRabbit

  • New Features

    • Added optional Moesif Analytics integration to track and monitor translation events with configurable settings.
  • Documentation

    • Updated configuration instructions with step-by-step Moesif Analytics setup guidance, including credential requirements and endpoint configuration.

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

@coderabbitai
Copy link

coderabbitai bot commented Nov 26, 2025

Walkthrough

This PR integrates Moesif analytics into the FTP-SFTP translator module. Changes include documentation for Moesif setup, new configuration blocks and types for analytics settings, dependency version update, and refactored logging to publish structured JSON events to both dashboard and Moesif endpoints.

Changes

Cohort / File(s) Summary
Documentation Updates
README.md, translator/integrations/ftp-sftp/README.md
Added optional Moesif Analytics sections with setup instructions, TOML snippets for Moesif configuration (enabled, applicationId, apiEndpoint, timeout, retry settings), and guidance to sign up and enable Moesif integration.
Configuration
translator/integrations/ftp-sftp/swiftMtMxTranslator/Config.toml
Replaced [translator] section with [translator.mxMtExtension] and [translator.mtMxExtension] extension blocks; added new [moesif] configuration block with settings for API integration (enabled, applicationId, apiEndpoint, timeout, retryCount, retryInterval, retryBackOffFactor, retryMaxWaitInterval).
Dependency
translator/integrations/ftp-sftp/swiftMtMxTranslator/Dependencies.toml
Bumped wso2/swiftMtMxTranslator package version from 2.0.3 to 2.0.5.
Type Definitions
translator/integrations/ftp-sftp/swiftMtMxTranslator/types.bal
Added MoesifConfig record type with enabled, applicationId, apiEndpoint, timeout, retryCount, retryInterval, retryBackOffFactor, and retryMaxWaitInterval fields with sensible defaults.
Configuration Declaration
translator/integrations/ftp-sftp/swiftMtMxTranslator/configurables.bal
Added public configurable MoesifConfig moesif variable.
Logging and Event Publishing
translator/integrations/ftp-sftp/swiftMtMxTranslator/utils.bal
Introduced moesifClient HTTP client initialization; refactored appendToDashboardLogs to accept structured JSON events; added createPublishableTranslationEvent and sendToMoesif functions; updated handleError, handleSkip, and handleSuccess flows to publish standardized JSON events to both dashboard and Moesif.

Sequence Diagram(s)

sequenceDiagram
    participant Handler as handleError/handleSkip/handleSuccess
    participant Event as createPublishableTranslationEvent
    participant Dashboard as Dashboard Logger
    participant Moesif as sendToMoesif
    participant Client as Moesif HTTP Client

    Handler->>Event: Build structured event<br/>(messages, IDs, metadata, status)
    Event-->>Handler: Return JSON event
    Handler->>Dashboard: appendToDashboardLogs(event)
    Dashboard->>Dashboard: Log JSON event
    Handler->>Moesif: sendToMoesif(event)
    Moesif->>Moesif: Transform to Moesif format
    Moesif->>Client: POST to Moesif API
    Client-->>Moesif: Response
    Moesif->>Moesif: Handle errors asynchronously
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Focus areas:
    • utils.bal: Verify refactored handleError, handleSkip, and handleSuccess flows correctly construct and publish JSON events; confirm createPublishableTranslationEvent properly structures all required fields with correct defaults.
    • utils.bal: Validate moesifClient initialization logic (async retry handling, timeout configuration, null-safety checks).
    • utils.bal: Confirm sendToMoesif worker implementation and error handling for external API calls.
    • Cross-file consistency: Ensure MoesifConfig type, configurables, and Config.toml entries align in field names and defaults.

Possibly related PRs

Suggested reviewers

  • RivinduM

Poem

🐰 Analytics flow now bright,
Moesif syncs each event's flight,
Structured JSON gleams with care,
Logs dance paired with grace to spare,
Translation tales fly fair and far! 📊✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is incomplete and only contains a placeholder. Critical sections from the template (Goals, Approach, User stories, Release note, Documentation, etc.) are missing. Complete the description by filling all required template sections: Goals, Approach, User stories, Release note, Documentation, Training, Certification, Marketing, test coverage, security checks, and other applicable sections.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding Moesif analytics integration to publish translation logs from the translator service.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


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: 2

🧹 Nitpick comments (3)
README.md (1)

116-133: Consider clarifying the Moesif and OpenSearch relationship.

Line 132 states "display real-time analytics from Moesif instead of OpenSearch," but based on utils.bal, dashboard logs are still written locally via appendToDashboardLogs (which writes to files that OpenSearch can index). Moesif appears to be an additional analytics channel rather than a replacement.

Consider rewording to: "This enables additional real-time analytics through Moesif alongside existing dashboard logging."

translator/integrations/ftp-sftp/swiftMtMxTranslator/utils.bal (2)

446-452: Inconsistent case sensitivity in error categorization.

The error message checks have inconsistent case handling:

  • "required" check is case-sensitive (line 446, 450)
  • "not supported" check is case-sensitive on line 447 but case-insensitive on line 448
  • "invalid" check is case-insensitive (line 448-449)

This could lead to errors being miscategorized. Consider normalizing the error message once:

+    string lowerErrorMsg = errorMsg.toLowerAscii();
     return {
         // ... other fields ...
-        "fieldError": errorMsg.includes("required") ? errorMsg : "",
-        "notSupportedError": errorMsg.toLowerAscii().includes("not supported") ? errorMsg : "",
-        "invalidError": errorMsg.toLowerAscii().includes("invalid")
-            && !errorMsg.toLowerAscii().includes("not supported") ? errorMsg : "",
-        "otherError": !errorMsg.includes("required") && !errorMsg.includes("not supported")
-            && !errorMsg.toLowerAscii().includes("invalid") ? errorMsg : ""
+        "fieldError": lowerErrorMsg.includes("required") ? errorMsg : "",
+        "notSupportedError": lowerErrorMsg.includes("not supported") ? errorMsg : "",
+        "invalidError": lowerErrorMsg.includes("invalid")
+            && !lowerErrorMsg.includes("not supported") ? errorMsg : "",
+        "otherError": !lowerErrorMsg.includes("required") && !lowerErrorMsg.includes("not supported")
+            && !lowerErrorMsg.includes("invalid") ? errorMsg : ""
     };

471-484: Unused variable statusValue in worker block.

The statusValue variable is extracted (lines 473-475) but never used in the Moesif action payload or elsewhere. This appears to be dead code that should be removed or utilized.

     worker MoesifWorker {
         do {
-            // Extract status for action name
-            json statusField = check publishableTranslationEvent.status;
-            string statusValue = statusField is string ? statusField : "";
-            
             // Transform to Moesif action format
             json moesifAction = {
                 "action_name": "translation_log",

Alternatively, if the intention was to include status in the action name:

-            "action_name": "translation_log",
+            "action_name": string `translation_${statusValue}`,
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 61febf2 and abe4e07.

📒 Files selected for processing (7)
  • README.md (1 hunks)
  • translator/integrations/ftp-sftp/README.md (1 hunks)
  • translator/integrations/ftp-sftp/swiftMtMxTranslator/Config.toml (2 hunks)
  • translator/integrations/ftp-sftp/swiftMtMxTranslator/Dependencies.toml (1 hunks)
  • translator/integrations/ftp-sftp/swiftMtMxTranslator/configurables.bal (1 hunks)
  • translator/integrations/ftp-sftp/swiftMtMxTranslator/types.bal (1 hunks)
  • translator/integrations/ftp-sftp/swiftMtMxTranslator/utils.bal (5 hunks)
🔇 Additional comments (6)
translator/integrations/ftp-sftp/README.md (1)

213-235: Documentation for Moesif Analytics is clear and complete.

The optional configuration section is well-documented with all required fields, default values, and setup steps. The TOML snippet aligns with the MoesifConfig type definition.

translator/integrations/ftp-sftp/swiftMtMxTranslator/Dependencies.toml (1)

418-441: Version bump looks appropriate for the new Moesif integration.

The package version update to 2.0.5 aligns with the new feature addition.

translator/integrations/ftp-sftp/swiftMtMxTranslator/configurables.bal (1)

115-125: Moesif configurable block is well-structured with sensible defaults.

  • enabled: false prevents accidental activation
  • Retry configuration with exponential backoff is appropriate for external API calls
  • Default timeout of 5 seconds is reasonable for analytics calls
translator/integrations/ftp-sftp/swiftMtMxTranslator/Config.toml (1)

117-131: Moesif configuration block is well-documented and safely disabled by default.

The placeholder applicationId and enabled = false ensure users must explicitly configure and enable the feature. Comments provide clear guidance.

translator/integrations/ftp-sftp/swiftMtMxTranslator/utils.bal (1)

46-58: Handler updates follow a consistent pattern for event publishing.

The refactored handleError, handleSkip, and handleSuccess functions consistently create publishable events and send them to both the dashboard (synchronous) and Moesif (asynchronous). This maintains backward compatibility while adding the new analytics capability.

translator/integrations/ftp-sftp/swiftMtMxTranslator/types.bal (1)

57-66: Type inconsistency for retryBackOffFactor is valid — but context-dependent on Ballerina http module version.

The concern about using float for retryBackOffFactor while other timeout/interval fields use decimal is legitimate:

  • Ballerina does NOT support implicit type coercion between float and decimal — they are distinct IEEE 754 types (binary64 vs decimal128 subset).
  • http:RetryConfig.backOffFactor type varies by version:
    • Older http module: backOffFactor is float
    • Newer Ballerina specs: backOffFactor is decimal
  • If using a newer Ballerina version, http:RetryConfig.backOffFactor expects decimal, requiring explicit conversion of the float value — creating unnecessary type friction.

The recommendation to use decimal consistently aligns with current Ballerina best practices and newer http module specifications. However, verify the exact http module version in Ballerina.toml to confirm whether this change is necessary or merely a consistency improvement.

 type MoesifConfig record {
     boolean enabled = false;
     string applicationId;
     string apiEndpoint = "https://api.moesif.net/v1/actions";
     decimal timeout = 5.0;
     int retryCount = 3;
     decimal retryInterval = 2.0;
-    float retryBackOffFactor = 2.0;
+    decimal retryBackOffFactor = 2.0;
     decimal retryMaxWaitInterval = 10.0;
 };

Comment on lines +25 to +34
// Initialize Moesif HTTP client (only if enabled)
final http:Client? moesifClient = moesif.enabled ? check new (moesif.apiEndpoint, {
timeout: moesif.timeout,
retryConfig: {
count: moesif.retryCount,
interval: moesif.retryInterval,
backOffFactor: moesif.retryBackOffFactor,
maxWaitInterval: moesif.retryMaxWaitInterval
}
}) : ();
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

Module-level check can crash the application on startup for a non-essential feature.

Using check in the module-level client initialization means any error (invalid apiEndpoint URL format, etc.) will cause the entire application to fail at startup. Analytics should fail gracefully without affecting core translation functionality.

Consider using error handling to make Moesif initialization failures non-fatal:

-final http:Client? moesifClient = moesif.enabled ? check new (moesif.apiEndpoint, {
-    timeout: moesif.timeout,
-    retryConfig: {
-        count: moesif.retryCount,
-        interval: moesif.retryInterval,
-        backOffFactor: moesif.retryBackOffFactor,
-        maxWaitInterval: moesif.retryMaxWaitInterval
-    }
-}) : ();
+final http:Client? moesifClient = initMoesifClient();
+
+function initMoesifClient() returns http:Client? {
+    if !moesif.enabled {
+        return ();
+    }
+    http:Client|error client = new (moesif.apiEndpoint, {
+        timeout: moesif.timeout,
+        retryConfig: {
+            count: moesif.retryCount,
+            interval: moesif.retryInterval,
+            backOffFactor: moesif.retryBackOffFactor,
+            maxWaitInterval: moesif.retryMaxWaitInterval
+        }
+    });
+    if client is error {
+        log:printError("Failed to initialize Moesif client. Analytics will be disabled.", err = client.toBalString());
+        return ();
+    }
+    return client;
+}
📝 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
// Initialize Moesif HTTP client (only if enabled)
final http:Client? moesifClient = moesif.enabled ? check new (moesif.apiEndpoint, {
timeout: moesif.timeout,
retryConfig: {
count: moesif.retryCount,
interval: moesif.retryInterval,
backOffFactor: moesif.retryBackOffFactor,
maxWaitInterval: moesif.retryMaxWaitInterval
}
}) : ();
// Initialize Moesif HTTP client (only if enabled)
final http:Client? moesifClient = initMoesifClient();
function initMoesifClient() returns http:Client? {
if !moesif.enabled {
return ();
}
http:Client|error client = new (moesif.apiEndpoint, {
timeout: moesif.timeout,
retryConfig: {
count: moesif.retryCount,
interval: moesif.retryInterval,
backOffFactor: moesif.retryBackOffFactor,
maxWaitInterval: moesif.retryMaxWaitInterval
}
});
if client is error {
log:printError("Failed to initialize Moesif client. Analytics will be disabled.", err = client.toBalString());
return ();
}
return client;
}

Comment on lines +477 to +484
// Transform to Moesif action format
json moesifAction = {
"action_name": "translation_log",
"request": {
"time": check publishableTranslationEvent.date
},
"metadata": publishableTranslationEvent
};
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

Consider privacy implications of sending full message content to Moesif.

The publishableTranslationEvent containing originalMessage and translatedMessage (which include full SWIFT MT/MX message content with financial transaction details) is sent to Moesif's external servers.

Consider:

  1. Documenting this data flow in the README (users should be aware PII/transaction data goes to a third-party)
  2. Adding an option to exclude message content from Moesif payloads:
// Option to send only metadata without message content
json moesifMetadata = moesif.excludeMessageContent ? 
    publishableTranslationEvent.clone() but { "originalMessage": "[redacted]", "translatedMessage": "[redacted]" } :
    publishableTranslationEvent;

This is especially relevant for SWIFT messages which may contain sensitive financial and PII data subject to regulations.

🤖 Prompt for AI Agents
In translator/integrations/ftp-sftp/swiftMtMxTranslator/utils.bal around lines
477 to 484, the code sends publishableTranslationEvent (including
originalMessage and translatedMessage) to Moesif which may leak sensitive
SWIFT/financial/PII data; add a configurable option (e.g.,
moesif.excludeMessageContent) and when enabled create a sanitized copy of
publishableTranslationEvent that replaces or removes originalMessage and
translatedMessage (e.g., set to "[redacted]" or omit the keys) and use that
sanitized object for moesifAction.metadata; additionally update the README to
document that message content is sent to Moesif and how to enable the
excludeMessageContent setting.

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.

1 participant