From b99c80c078c0e0b35384ff64ef0d0426d1f73a9c Mon Sep 17 00:00:00 2001 From: Satish Kumar Date: Wed, 31 Jul 2024 17:39:56 +0530 Subject: [PATCH 1/2] chore: include enrichment plugin code in alerta --- .dockerignore | 1 + .github/workflows/pr-onto-dev.yaml | 10 ---------- .gitignore | 1 - rudder-alerta-enrichment-plugin | 1 + 4 files changed, 2 insertions(+), 11 deletions(-) create mode 160000 rudder-alerta-enrichment-plugin diff --git a/.dockerignore b/.dockerignore index af09f1641..a4ecc13f6 100644 --- a/.dockerignore +++ b/.dockerignore @@ -8,3 +8,4 @@ venv .coverage *.swp *.log +.git diff --git a/.github/workflows/pr-onto-dev.yaml b/.github/workflows/pr-onto-dev.yaml index 934030714..805b9308d 100644 --- a/.github/workflows/pr-onto-dev.yaml +++ b/.github/workflows/pr-onto-dev.yaml @@ -13,19 +13,9 @@ jobs: - name: Get branch name id: branch-name uses: tj-actions/branch-names@v5.1 - # - run: git fetch --all --tags - # - name: Check Release Version - # uses: thebongy/version-check@v1 - # with: - # file: worker/package.json - # tagFormat: v${version} - # failBuild: true - run: | docker login --username rudderlabs --password '${{ secrets.DOCKER_HUB_PASSWORD }}' export VERSION=${{ steps.branch-name.outputs.current_branch }} - rm -rf rudder-alerta-enrichment-plugin - git clone -b "$(cat RUDDER_ENRICH_PLUGIN_BRANCH_NAME)" https://${{ secrets.PAT_USERNAME }}:${{ secrets.PAT }}@github.com/rudderlabs/rudder-alerta-enrichment-plugin.git docker build --no-cache --build-arg=COMMIT_ID_VALUE="$(git log --format="%H" -n 1)" -t rudderlabs/alerta:$VERSION . docker push rudderlabs/alerta:$VERSION - rm -rf rudder-alerta-enrichment-plugin name: Docker build and push \ No newline at end of file diff --git a/.gitignore b/.gitignore index e25abd35c..18203f944 100644 --- a/.gitignore +++ b/.gitignore @@ -117,5 +117,4 @@ pg-data/ .env.development values.yaml -rudder-alerta-enrichment-plugin/ pg-data-2 \ No newline at end of file diff --git a/rudder-alerta-enrichment-plugin b/rudder-alerta-enrichment-plugin new file mode 160000 index 000000000..ee19fb172 --- /dev/null +++ b/rudder-alerta-enrichment-plugin @@ -0,0 +1 @@ +Subproject commit ee19fb17285563914af8c3ae063fd0b50f9aa6c6 From aa307a9cb48ae6eaabd8035c65697a0c34336bfb Mon Sep 17 00:00:00 2001 From: Satish Kumar Date: Wed, 31 Jul 2024 17:43:50 +0530 Subject: [PATCH 2/2] include enrichment code --- rudder-alerta-enrichment-plugin | 1 - .../.github/workflows/sync-ditto-changes.yaml | 11 + .../ditto/config.yml | 3 + .../ditto/index.js | 1801 ++++++++++++++ .../ditto/text.json | 2095 +++++++++++++++++ .../requirements.txt | 2 + .../rudder_enrichment/__init__.py | 1 + .../config_backend_client.py | 15 + .../rudder_enrichment/environment.py | 26 + .../rudder_enrichment/rudder_enrichment.py | 204 ++ .../rudder_enrichment_models/Connection.py | 32 + .../rudder_enrichment_models/Destination.py | 52 + .../rudder_enrichment_models/Enrichment.py | 133 ++ .../rudder_enrichment_models/Source.py | 47 + .../Transformation.py | 57 + .../rudder_enrichment_models/Workspace.py | 38 + .../rudder_enrichment_models/__init__.py | 4 + .../rudder_enrichment_models/constants.py | 8 + .../ditto/BaseDittoEnrichment.py | 181 ++ .../ditto/ConnectionDittoEnrichment.py | 45 + .../ditto/DestinationDittoEnrichment.py | 31 + .../ditto/DittoEnrichmentFactory.py | 91 + .../ditto/SourceDittoEnrichment.py | 34 + .../ditto/TransformationDittoEnrichment.py | 33 + .../ditto/__init__.py | 5 + .../ditto/projects.py | 36 + .../rudder_enrichment_models/utils.py | 12 + rudder-alerta-enrichment-plugin/setup.py | 22 + 28 files changed, 5019 insertions(+), 1 deletion(-) delete mode 160000 rudder-alerta-enrichment-plugin create mode 100644 rudder-alerta-enrichment-plugin/.github/workflows/sync-ditto-changes.yaml create mode 100644 rudder-alerta-enrichment-plugin/ditto/config.yml create mode 100644 rudder-alerta-enrichment-plugin/ditto/index.js create mode 100644 rudder-alerta-enrichment-plugin/ditto/text.json create mode 100644 rudder-alerta-enrichment-plugin/requirements.txt create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/__init__.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/config_backend_client.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/environment.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Connection.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Destination.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Enrichment.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Source.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Transformation.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Workspace.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/__init__.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/constants.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/BaseDittoEnrichment.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/ConnectionDittoEnrichment.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/DestinationDittoEnrichment.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/DittoEnrichmentFactory.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/SourceDittoEnrichment.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/TransformationDittoEnrichment.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/__init__.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/projects.py create mode 100644 rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/utils.py create mode 100644 rudder-alerta-enrichment-plugin/setup.py diff --git a/rudder-alerta-enrichment-plugin b/rudder-alerta-enrichment-plugin deleted file mode 160000 index ee19fb172..000000000 --- a/rudder-alerta-enrichment-plugin +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ee19fb17285563914af8c3ae063fd0b50f9aa6c6 diff --git a/rudder-alerta-enrichment-plugin/.github/workflows/sync-ditto-changes.yaml b/rudder-alerta-enrichment-plugin/.github/workflows/sync-ditto-changes.yaml new file mode 100644 index 000000000..b019a4a13 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/.github/workflows/sync-ditto-changes.yaml @@ -0,0 +1,11 @@ +name: Sync Ditto Changes +on: workflow_dispatch + +jobs: + sync-ditto-changes: + runs-on: ubuntu-latest + steps: + - name: Sync Ditto Changes and create a PR + uses: dittowords/ditto-github-action@v0.2.0 + with: + ditto-api-key: ${{ secrets.DITTO_API_KEY }} \ No newline at end of file diff --git a/rudder-alerta-enrichment-plugin/ditto/config.yml b/rudder-alerta-enrichment-plugin/ditto/config.yml new file mode 100644 index 000000000..815a16c0e --- /dev/null +++ b/rudder-alerta-enrichment-plugin/ditto/config.yml @@ -0,0 +1,3 @@ +projects: + - name: "\U0001F6A8 Notifications & Alerts" + id: 630f9ed947a50a5d161c8b30 diff --git a/rudder-alerta-enrichment-plugin/ditto/index.js b/rudder-alerta-enrichment-plugin/ditto/index.js new file mode 100644 index 000000000..caf81cb28 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/ditto/index.js @@ -0,0 +1,1801 @@ +module.exports = { + "project_630f9ed947a50a5d161c8b30": { + "base": { + "frame_630f9ed9913de551b054b2d3": { + "frameName": "Souce Notification Settings - Admin, Disabled", + "blocks": { + "toggle-settings": { + "text_630f9ed9913de551b054b52b": { + "text": "Enable notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b531": { + "text": "Allow members to subscribe to notifications for this source", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b537": { + "text": "Notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b53d": { + "text": "Subscribe to email alerts for critical data delivery issues. Manage your alerts and subscriptions list in Notification settings.", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b578": { + "text": "You must first enable notifications for this source", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_630f9ed9913de551b054b2d2": { + "frameName": "Souce Notification Settings - Admin, Enabled", + "blocks": { + "toggle-settings": { + "text_630f9ed9913de551b054b4ab": { + "text": "Enable notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4b1": { + "text": "Allow members to subscribe to notifications for this source", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4bf": { + "text": "Notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4c5": { + "text": "Subscribe to email alerts for critical data delivery issues. Manage your alerts and subscriptions list in Notification settings.", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_630f9ed9913de551b054b2d4": { + "frameName": "Souce Notification Settings - Non-admin, Disabled", + "blocks": { + "toggle-settings": { + "text_630f9ed9913de551b054b585": { + "text": "Notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b58b": { + "text": "Subscribe to email alerts for critical data delivery issues. Manage your alerts and subscriptions list in Notification settings.", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b5b0": { + "text": "An admin must first enable notifications for this source", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_630f9ed9913de551b054b2d6": { + "frameName": "Destination Notification Settings - Admin, Disabled", + "blocks": { + "toggle-settings": { + "text_630f9ed9913de551b054b564": { + "text": "Enable notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b56c": { + "text": "Allow members to subscribe to notifications for this destination", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b5a5": { + "text": "You must first enable notifications for this destination", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_630f9ed9913de551b054b2d5": { + "frameName": "Destination Notification Settings - Admin, Enabled", + "blocks": { + "toggle-settings": { + "text_630f9ed9913de551b054b4b7": { + "text": "Enable notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4cb": { + "text": "Allow members to subscribe to notifications for this destination", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4e1": { + "text": "Notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4f4": { + "text": "Subscribe to email alerts for critical data delivery issues. Manage your alerts and subscriptions list in Notification settings.", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_630f9ed9913de551b054b2d7": { + "frameName": "Destination Notification Settings - Non-admin, Disabled", + "blocks": { + "toggle-settings": { + "text_630f9ed9913de551b054b49f": { + "text": "Notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4a9": { + "text": "Subscribe to email alerts for critical data delivery issues. Manage your alerts and subscriptions list in Notification settings.", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4f1": { + "text": "An admin must first enable notifications for this destination", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_630f9ed9913de551b054b2d8": { + "frameName": "Manage Notifications - Email Toggle", + "blocks": { + "settings": { + "text_630f9ed9913de551b054b412": { + "text": "Data delivery alerts", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b418": { + "text": "Receive email alerts for critical data delivery issues.", + "status": "FINAL" + }, + "text_6328e6392a50c243b9354350": { + "text": "Learn more", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b432": { + "text": "Email alerts", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b444": { + "text": "kland@rudderstack.com", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b462": { + "text": "2 Subscription(s)", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b44a": { + "text": "Manage subscriptions", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_630f9ed9913de551b054b2d9": { + "frameName": "Manage Notifications - Subscription List", + "blocks": { + "subscriptions": { + "text_630f9ed9913de551b054b5b1": { + "text": "Manage subscriptions", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b554": { + "text": "Receive data delivery alerts for subscribed sources.", + "variants": { + "list---destinations": { + "text": "Receive data delivery alerts for subscribed destinations." + }, + "list---warehouses": { + "text": "Receive data delivery alerts for subscribed warehouse destinations." + } + }, + "status": "FINAL" + }, + "text_630f9ed9913de551b054b566": { + "text": "Source subscribed", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b56e": { + "text": "Name", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b57d": { + "text": "Subscribed", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b583": { + "text": "Source name", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b58f": { + "text": "Source name", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_data_delivery_alert": { + "frameName": "Data Delivery Alert", + "blocks": { + "alert-copy": { + "body_heading_old": { + "text": "[Email Body Title] E.g., Event Volume Drop", + "variants": { + "event-volume-drops": { + "text": "Event Volume Drop" + }, + "transformation-error": { + "text": "Transformation Error" + } + }, + "status": "REVIEW", + "notes": "Title in the email body" + }, + "greeting_old": { + "text": "[Greeting] Hello {{customer}} Team", + "variants": { + "event-volume-drops": { + "text": "Hello {{customer}} Team" + } + }, + "status": "WIP", + "notes": "Greeting line in email body", + "variables": { + "customer": { + "example": "Demo Customer" + } + } + }, + "body_old": { + "text": "[Email Body] E.g., “We’ve detected a recent drop in event volume of greater than 25% (vs. the last 7 days) from {{source}} and recommend looking into this issue further.”", + "variants": { + "event-volume-drops": { + "text": "We’ve detected a recent drop in event volume of greater than 25% (vs. the last 7 days) from {{source}} and recommend looking into this issue further." + }, + "delivery-lag": { + "text": "[Email Body] E.g., “We’ve detected a recent drop in event volume of greater than 25% (vs. the last 7 days) {{destination_wh}} and recommend looking into this issue further.”", + "variables": { + "destination_wh": { + "example": "Demo WH Destination" + } + } + } + }, + "status": "WIP", + "notes": "Email body", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "" + } + } + }, + "cta_button_link_old": { + "text": "[CTA Location / Resource]", + "variants": { + "event-volume-drops": { + "text": "{{cp_base_url_old}}/sources/{{source_id_old}}?tab=Events", + "variables": { + "cp_base_url_old": { + "example": "https://app.rudderlabs.com" + }, + "source_id_old": { + "example": "abcde" + } + } + } + }, + "status": "WIP", + "notes": "[CTA Button Link] This will be a dynamic field to insert the location or resource that triggered the alert. We can take the user to events tab of the affected source for event volume drop case" + }, + "cta_button_text_old": { + "text": "[CTA Button] E.g., View Events for {{source}}", + "variants": { + "event-volume-drops": { + "text": "View Events from {{source}}" + } + }, + "status": "WIP", + "notes": "CTA Button Text", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "" + } + } + }, + "signature_old": { + "text": "[RudderStack Signature]", + "variants": { + "event-volume-drops": { + "text": "RudderStack Team" + } + }, + "status": "WIP", + "notes": "RudderStack Signature" + } + } + }, + "otherText": { + "text_631771ab9d5a185c751a2674": { + "text": "shield-halved#" + }, + "text_631771ab9d5a185c751a2676": { + "text": "shield-halved##" + }, + "text_631771ab9d5a185c751a2684": { + "text": "©2022 RudderStack" + }, + "text_631771ab9d5a185c751a2686": { + "text": "View in Browser" + } + } + }, + "frame_631e3e715a90787937342451": { + "frameName": "Transformation Notification Settings - Admin, Enabled", + "blocks": {}, + "otherText": { + "text_631e3e715a90787937342464": { + "text": "arrow-left-from-line" + }, + "text_631e3e715a9078793734246a": { + "text": "Acme Corp." + }, + "text_631e3e715a90787937342470": { + "text": "john@rudderstack.com" + }, + "text_631e3e715a90787937342478": { + "text": "angle-right" + }, + "text_631e3e715a9078793734247e": { + "text": "Directory" + }, + "text_631e3e715a90787937342484": { + "text": "Connect" + }, + "text_631e3e715a9078793734248a": { + "text": "angle-right" + }, + "text_631e3e715a90787937342490": { + "text": "Enhance" + }, + "text_631e3e715a90787937342496": { + "text": "angle-down" + }, + "text_631e3e715a9078793734249c": { + "text": "Transformations" + }, + "text_631e3e715a907879373424a2": { + "text": "Models" + }, + "text_631e3e715a907879373424a8": { + "text": "Audiences" + }, + "text_631e3e715a907879373424ae": { + "text": "Monitor" + }, + "text_631e3e715a907879373424b4": { + "text": "angle-right" + }, + "text_631e3e715a907879373424ba": { + "text": "Settings" + }, + "text_631e3e715a907879373424c0": { + "text": "bolt" + }, + "text_631e3e715a907879373424c6": { + "text": "Getting started" + }, + "text_631e3e715a907879373424cc": { + "text": "book-open-cover" + }, + "text_631e3e715a907879373424d2": { + "text": "Docs & Support" + }, + "text_631e3e715a907879373424d8": { + "text": "All transformations" + }, + "text_631e3e715a907879373424de": { + "text": "arrow-left" + }, + "text_631e3e715a907879373424e4": { + "text": "/" + }, + "text_631e3e715a907879373424ea": { + "text": "Test6" + }, + "text_631e3e715a907879373424f0": { + "text": "Test 6" + }, + "text_631e3e715a907879373424f6": { + "text": "Description displayed here" + }, + "text_631e3e715a907879373424fc": { + "text": "Live events" + }, + "text_631e3e715a90787937342502": { + "text": "Transformation" + }, + "text_631e3e715a90787937342508": { + "text": "Connections" + }, + "text_631e3e715a9078793734250e": { + "text": "Settings" + }, + "text_631e3e715a90787937342514": { + "text": "General info" + }, + "text_631e3e715a9078793734251a": { + "text": "These are the basic details needed to set up your transformation." + }, + "text_631e3e715a90787937342520": { + "text": "Transforamtion name" + }, + "text_631e3e715a90787937342526": { + "text": "Test 6" + }, + "text_631e3e715a9078793734252c": { + "text": "Transformation description (optional)" + }, + "text_631e3e715a90787937342532": { + "text": "Description of audience here" + }, + "text_631e3e715a90787937342536": { + "text": "pencil" + }, + "text_63288c4532871c3a8efb0678": { + "text": "Notifications" + }, + "text_63288c4532871c3a8efb067a": { + "text": "Enable notifications" + }, + "text_63288c4532871c3a8efb067c": { + "text": "Turn on notifications for this transformation for everyone" + }, + "text_63288c4532871c3a8efb067e": { + "text": "check" + }, + "text_63288c4532871c3a8efb0680": { + "text": "Notifications" + }, + "text_63288c4532871c3a8efb0682": { + "text": "Receive data-delivery alerts. You can manage these in the “subscription” list within Notification settings." + }, + "text_6328bf8f664f6c2de14e2aba": { + "text": "xmark" + }, + "text_631e3e715a90787937342552": { + "text": "Danger zone" + }, + "text_631e3e715a90787937342556": { + "text": "radiation" + }, + "text_631e3e715a9078793734255a": { + "text": "Permanently delete transformation" + }, + "text_631e3e715a90787937342560": { + "text": "Once confirmed, this operation can't be undone!" + }, + "text_631e3e715a90787937342565": { + "text": "trash-can" + }, + "text_631e3e715a90787937342569": { + "text": "Delete" + } + } + }, + "frame_631e3e715a9078793734244d": { + "frameName": "Transformation Notification Settings - Admin, Disabled", + "blocks": { + "toggle-settings": { + "text_631e3e715a90787937342538": { + "text": "Enable notifications", + "status": "FINAL" + }, + "text_631e3e715a9078793734253e": { + "text": "Turn on notifications for this transformation for everyone" + }, + "text_631e3e715a90787937342544": { + "text": "Notifications", + "status": "FINAL" + }, + "text_631e3e715a9078793734254a": { + "text": "Receive data-delivery alerts. You can manage these in the “subscription” list within Notification settings." + } + } + }, + "otherText": { + "text_631e3e715a90787937342460": { + "text": "arrow-left-from-line" + }, + "text_631e3e715a90787937342466": { + "text": "Acme Corp." + }, + "text_631e3e715a9078793734246c": { + "text": "john@rudderstack.com" + }, + "text_631e3e715a90787937342472": { + "text": "angle-right" + }, + "text_631e3e715a90787937342476": { + "text": "Directory" + }, + "text_631e3e715a9078793734247c": { + "text": "Connect" + }, + "text_631e3e715a90787937342482": { + "text": "angle-right" + }, + "text_631e3e715a90787937342488": { + "text": "Enhance" + }, + "text_631e3e715a9078793734248e": { + "text": "angle-down" + }, + "text_631e3e715a90787937342494": { + "text": "Transformations" + }, + "text_631e3e715a9078793734249a": { + "text": "Models" + }, + "text_631e3e715a907879373424a0": { + "text": "Audiences" + }, + "text_631e3e715a907879373424a6": { + "text": "Monitor" + }, + "text_631e3e715a907879373424ac": { + "text": "angle-right" + }, + "text_631e3e715a907879373424b2": { + "text": "Settings" + }, + "text_631e3e715a907879373424b8": { + "text": "bolt" + }, + "text_631e3e715a907879373424be": { + "text": "Getting started" + }, + "text_631e3e715a907879373424c4": { + "text": "book-open-cover" + }, + "text_631e3e715a907879373424ca": { + "text": "Docs & Support" + }, + "text_631e3e715a907879373424d0": { + "text": "All transformations" + }, + "text_631e3e715a907879373424d6": { + "text": "arrow-left" + }, + "text_631e3e715a907879373424dc": { + "text": "/" + }, + "text_631e3e715a907879373424e2": { + "text": "Test6" + }, + "text_631e3e715a907879373424e8": { + "text": "Test 6" + }, + "text_631e3e715a907879373424ee": { + "text": "Description displayed here" + }, + "text_631e3e715a907879373424f4": { + "text": "Live events" + }, + "text_631e3e715a907879373424fa": { + "text": "Transformation" + }, + "text_631e3e715a90787937342500": { + "text": "Connections" + }, + "text_631e3e715a90787937342506": { + "text": "Settings" + }, + "text_631e3e715a9078793734250c": { + "text": "General info" + }, + "text_631e3e715a90787937342512": { + "text": "These are the basic details needed to set up your transformation." + }, + "text_631e3e715a90787937342518": { + "text": "Transforamtion name" + }, + "text_631e3e715a9078793734251e": { + "text": "Test 6" + }, + "text_631e3e715a90787937342524": { + "text": "Transformation description (optional)" + }, + "text_631e3e715a9078793734252a": { + "text": "Description of audience here" + }, + "text_63282355352ef745b29f7165": { + "text": "pencil" + }, + "text_63282355352ef745b29f7169": { + "text": "Notifications" + }, + "text_6324dafac4fb2d4b6b651813": { + "text": "xmark" + }, + "text_6324dafac4fb2d4b6b65182e": { + "text": "xmark" + }, + "text_631e3e715a90787937342550": { + "text": "Danger zone" + }, + "text_631e3e715a90787937342558": { + "text": "radiation" + }, + "text_631e3e715a9078793734255e": { + "text": "Permanently delete transformation" + }, + "text_631e3e715a90787937342563": { + "text": "Once confirmed, this operation can't be undone!" + }, + "text_631e3e715a90787937342567": { + "text": "trash-can" + }, + "text_631e3e715a9078793734256a": { + "text": "Delete" + }, + "text_631e3e715a9078793734256c": { + "text": "Notifications for this transformation have been disabled" + } + } + }, + "frame_631e3e715a9078793734244f": { + "frameName": "Transformation Notification Settings - Non-admin, Disabled", + "blocks": { + "toggle-settings": { + "text_631e3e715a9078793734252e": { + "text": "Notifications", + "status": "FINAL" + }, + "text_631e3e715a90787937342534": { + "text": "Receive data-delivery alerts. You can manage these in the “subscription” list within Notification settings." + }, + "text_631e3e715a90787937342562": { + "text": "Notifications for this transformation have been disabled" + } + } + }, + "otherText": { + "text_631e3e715a9078793734245a": { + "text": "arrow-left-from-line" + }, + "text_631e3e715a9078793734245d": { + "text": "Acme Corp." + }, + "text_631e3e715a90787937342462": { + "text": "john@rudderstack.com" + }, + "text_631e3e715a90787937342468": { + "text": "angle-right" + }, + "text_631e3e715a9078793734246e": { + "text": "Directory" + }, + "text_631e3e715a90787937342474": { + "text": "Connect" + }, + "text_631e3e715a9078793734247a": { + "text": "angle-right" + }, + "text_631e3e715a90787937342480": { + "text": "Enhance" + }, + "text_631e3e715a90787937342486": { + "text": "angle-down" + }, + "text_631e3e715a9078793734248c": { + "text": "Transformations" + }, + "text_631e3e715a90787937342492": { + "text": "Models" + }, + "text_631e3e715a90787937342498": { + "text": "Audiences" + }, + "text_631e3e715a9078793734249e": { + "text": "Monitor" + }, + "text_631e3e715a907879373424a4": { + "text": "angle-right" + }, + "text_631e3e715a907879373424aa": { + "text": "Settings" + }, + "text_631e3e715a907879373424b0": { + "text": "bolt" + }, + "text_631e3e715a907879373424b6": { + "text": "Getting started" + }, + "text_631e3e715a907879373424bc": { + "text": "book-open-cover" + }, + "text_631e3e715a907879373424c2": { + "text": "Docs & Support" + }, + "text_631e3e715a907879373424c8": { + "text": "All transformations" + }, + "text_631e3e715a907879373424ce": { + "text": "arrow-left" + }, + "text_631e3e715a907879373424d4": { + "text": "/" + }, + "text_631e3e715a907879373424da": { + "text": "Test6" + }, + "text_631e3e715a907879373424e0": { + "text": "Test 6" + }, + "text_631e3e715a907879373424e6": { + "text": "Description displayed here" + }, + "text_631e3e715a907879373424ec": { + "text": "Live events" + }, + "text_631e3e715a907879373424f2": { + "text": "Transformation" + }, + "text_631e3e715a907879373424f8": { + "text": "Connections" + }, + "text_631e3e715a907879373424fe": { + "text": "Settings" + }, + "text_63282355352ef745b29f7167": { + "text": "General info" + }, + "text_63282355352ef745b29f716a": { + "text": "These are the basic details needed to set up your transformation." + }, + "text_63282355352ef745b29f716c": { + "text": "Transforamtion name" + }, + "text_63282355352ef745b29f716e": { + "text": "Test 6" + }, + "text_63282355352ef745b29f7170": { + "text": "Transformation description (optional)" + }, + "text_63282355352ef745b29f7172": { + "text": "Description of audience here" + }, + "text_63282355352ef745b29f7174": { + "text": "pencil" + }, + "text_6324dafac4fb2d4b6b651815": { + "text": "xmark" + }, + "text_631e3e715a9078793734253a": { + "text": "Danger zone" + }, + "text_631e3e715a90787937342540": { + "text": "radiation" + }, + "text_631e3e715a90787937342546": { + "text": "Permanently delete transformation" + }, + "text_631e3e715a9078793734254c": { + "text": "Once confirmed, this operation can't be undone!" + }, + "text_631e3e715a90787937342554": { + "text": "trash-can" + }, + "text_631e3e715a9078793734255c": { + "text": "Delete" + } + } + }, + "frame_SES_Alert": { + "frameName": "Current Amazon SES Email Template", + "blocks": { + "amazon-ses-template": { + "subject": { + "text": "[Error Type] | {{source}}", + "variants": { + "event-volume-drops": { + "text": "Event Volume Drop Warning | {{source}}", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "" + } + } + }, + "delivery-error": { + "text": "Delivery Error | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + }, + "discards": { + "text": "Data Type Mismatch | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + }, + "invalid-json": { + "text": "Invalid JSON | {{source}}", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "" + } + } + }, + "tracking-plan-event-drops": { + "text": "Event Dropped by Tracking Plan | {{source}}", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "" + } + } + }, + "transformation-error": { + "text": "Transformation Error | {{transformation}}", + "variables": { + "transformation": { + "example": "Demo Transformation" + } + } + }, + "delivery-error---wh-destination": { + "text": "Delivery Error | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + }, + "delivery-lag---wh-destination": { + "text": "Delivery Lag | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + }, + "delivery-lag---cloud-destination": { + "text": "Delivery Lag | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + }, + "badris-notification": { + "text": "Badri’s Error | {{source}}", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "" + } + } + }, + "warehouse-column-count": { + "text": "Delivery warning | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + }, + "event-volume-drop-destination": { + "text": "Event Volume Drop Warning | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + }, + "warehouse-column-changes": { + "text": "Warehouse columns changes | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + } + }, + "status": "FINAL", + "notes": "Subject line of email", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "" + } + } + }, + "body_heading": { + "text": "[Error Type]", + "variants": { + "event-volume-drops": { + "text": "Event Volume Drop Warning" + }, + "delivery-error": { + "text": "Delivery Error" + }, + "discards": { + "text": "Data Type Mismatch" + }, + "invalid-json": { + "text": "Invalid JSON" + }, + "tracking-plan-event-drops": { + "text": "Event Dropped by Tracking Plan" + }, + "transformation-error": { + "text": "Transformation Error" + }, + "delivery-error---wh-destination": { + "text": "Delivery Error" + }, + "delivery-lag---wh-destination": { + "text": "Delivery Lag" + }, + "delivery-lag---cloud-destination": { + "text": "Delivery Lag" + }, + "warehouse-column-count": { + "text": "Delivery warning" + }, + "event-volume-drop-destination": { + "text": "Event Volume Drop Warning" + }, + "warehouse-column-changes": { + "text": "Action required: Drop outdated columns" + } + }, + "status": "FINAL" + }, + "greeting": { + "text": "Hi {{customer}} Team,", + "variants": { + "event-volume-drops": { + "text": "Hi {{customer}} Team,", + "variables": { + "customer": { + "example": "Demo Customer" + } + } + }, + "event-volume-drop-destination": { + "text": "Hi {{customer}} Team,", + "variables": { + "customer": { + "example": "Demo Customer" + } + } + } + }, + "status": "FINAL", + "variables": { + "customer": { + "example": "Demo Customer" + } + } + }, + "body": { + "text": "“We’ve detected [error type] from {{source}} and recommend looking into this issue further.”", + "variants": { + "event-volume-drops": { + "text": "We’ve noticed a large drop in your event volume in the last 24 hours. Your event volume dropped more than 25% compared to the last 7 days. We recommend you to look a closer look at {{source}} source.", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "" + } + } + }, + "delivery-error": { + "text": "We’ve detected a delivery error with {{destination}} and recommend taking a closer look.", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + }, + "discards": { + "text": "We’ve detected a data type mismatch that has resulted in a warehouse discard. We recommend taking a closer look." + }, + "invalid-json": { + "text": "We’ve detected an invalid JSON related to {{source}} and recommend taking a closer look.", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "" + } + } + }, + "tracking-plan-event-drops": { + "text": "A tracking plan has caused one or more events to be dropped. We recommend taking a closer look." + }, + "transformation-error": { + "text": "We’ve detected a transformation error with {{transformation}} and recommend taking a closer look.", + "variables": { + "transformation": { + "example": "Demo Transformation" + } + } + }, + "delivery-error---wh-destination": { + "text": "We’ve detected a delivery error with {{destination}} and recommend taking a closer look.", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + }, + "delivery-lag---wh-destination": { + "text": "We’ve detected a delivery lag with {{destination}} and recommend taking a closer look.", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + }, + "delivery-lag---cloud-destination": { + "text": "We’ve detected a delivery lag with {{destination}} and recommend taking a closer look.", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + }, + "warehouse-column-count": { + "text": "We’ve noticed that you’re reaching your column limit in your {{tableName}} table.
Your current table has {{currentColumnCount}} columns where only {{columnCountLimit}} are allowed. Exceeding this column limit may result in a data delivery error. Please refer to the RudderStack documentation for managing the number of columns in your Warehouse.", + "variables": { + "tableName": { + "example": "Demo Table" + }, + "currentColumnCount": { + "example": 950 + }, + "columnCountLimit": { + "example": 1000 + } + } + }, + "event-volume-drop-destination": { + "text": "We’ve noticed a large drop in your event volume in the last 24 hours. Your event volume dropped more than 25% compared to the last 7 days. We recommend you to look a closer look at {{destination}} destination.", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + }, + "warehouse-column-changes": { + "text": "Warehouse column names are not matching to the destination views as the views are outdated. Recreate your views so that they point to the latest column names and then drop the older columns. Please use the queries in the documentation to drop the columns" + } + }, + "status": "FINAL", + "notes": "Email body", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "" + } + } + }, + "cta_button_text": { + "text": "Review [Error Type]", + "variants": { + "event-volume-drops": { + "text": "Review Event Volume" + }, + "delivery-error": { + "text": "Review Delivery Error" + }, + "discards": { + "text": "Review Data Type Mismatch" + }, + "invalid-json": { + "text": "Review Invalid JSON" + }, + "tracking-plan-event-drops": { + "text": "Review Tracking Plan" + }, + "transformation-error": { + "text": "Review Transformation" + }, + "delivery-error---wh-destination": { + "text": "Review {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + }, + "delivery-lag---wh-destination": { + "text": "Review Delivery Lag" + }, + "delivery-lag---cloud-destination": { + "text": "Review Delivery Lag" + }, + "warehouse-column-count": { + "text": "Review {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + }, + "event-volume-drop-destination": { + "text": "Review Event Volume" + }, + "warehouse-column-changes": { + "text": "Review {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination" + } + } + } + }, + "status": "FINAL", + "notes": "Copy for CTA button" + }, + "cta_button_link": { + "text": "[CTA Location / Resource]", + "variants": { + "event-volume-drops": { + "text": "{{cp_base_url}}/sources/{{source_id}}?tab=Events", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com" + }, + "source_id": { + "example": "" + } + } + }, + "delivery-error": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Events", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com" + }, + "destination_id": { + "example": "" + } + } + }, + "delivery-error---wh-destination": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Syncs", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com" + }, + "destination_id": { + "example": "" + } + } + }, + "discards": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Syncs", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com" + }, + "destination_id": { + "example": "" + } + } + }, + "invalid-json": { + "text": "{{cp_base_url}}/sources/{{source_id}}?tab=Events", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com" + }, + "source_id": { + "example": "" + } + } + }, + "tracking-plan-event-drops": { + "text": "{{cp_base_url}}/sources/{{source_id}}?tab=Events", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com" + }, + "source_id": { + "example": "" + } + } + }, + "transformation-error": { + "text": "{{cp_base_url}}/transformations/{{transformation_id}}", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com" + }, + "transformation_id": { + "example": "" + } + } + }, + "delivery-lag---wh-destination": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Syncs", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com" + }, + "destination_id": { + "example": "" + } + } + }, + "delivery-lag---cloud-destination": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Events", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com" + }, + "destination_id": { + "example": "" + } + } + }, + "warehouse-column-count": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Syncs", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com" + }, + "destination_id": { + "example": "" + } + } + }, + "event-volume-drop-destination": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Events", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com" + }, + "destination_id": { + "example": "" + } + } + }, + "warehouse-column-changes": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Syncs", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com" + }, + "destination_id": { + "example": "" + } + } + } + }, + "status": "FINAL", + "notes": "[CTA Button Link] This will be a dynamic field to insert the location or resource that triggered the alert. We can take the user to events tab of the affected source for event volume drop case" + }, + "signature": { + "text": "— RudderStack Team", + "variants": { + "event-volume-drops": { + "text": "— RudderStack Team" + } + }, + "status": "FINAL", + "notes": "Signature" + }, + "manage_alerts": { + "text": "Manage the email alerts you receive in Notification Settings.", + "status": "FINAL" + }, + "manage_alerts_link": { + "text": "{{cp_base_url}}/profile", + "status": "REVIEW", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com" + } + } + } + } + }, + "otherText": {} + }, + "frame_636ab6d00a4046aadf62deed": { + "frameName": "Announcement banner", + "blocks": {}, + "otherText": { + "text_636ab6d00a4046aadf62def7": { + "text": "Your current promo of 5M events per month is expiring on December 31, 2022. Learn more" + }, + "text_636ab6d00a4046aadf62def9": { + "text": "circle-info" + }, + "text_636ab6d00a4046aadf62deff": { + "text": "xmark" + }, + "text_636ab6d00a4046aadf62df01": { + "text": "arrow-left-from-line" + }, + "text_636ab6d00a4046aadf62df03": { + "text": "Workspace" + }, + "text_636ab6d00a4046aadf62df05": { + "text": "Acme Corp." + }, + "text_636ab6d00a4046aadf62df0b": { + "text": "angle-right" + }, + "text_636ab6d00a4046aadf62df13": { + "text": "Directory" + }, + "text_636ab6d00a4046aadf62df19": { + "text": "Connect" + }, + "text_636ab6d00a4046aadf62df1b": { + "text": "angle-down" + }, + "text_636ab6d00a4046aadf62df1d": { + "text": "Connections" + }, + "text_636ab6d00a4046aadf62df21": { + "text": "Sources" + }, + "text_636ab6d00a4046aadf62df27": { + "text": "Destinations" + }, + "text_636ab6d00a4046aadf62df29": { + "text": "Enhance" + }, + "text_636ab6d00a4046aadf62df2d": { + "text": "angle-right" + }, + "text_636ab6d00a4046aadf62df31": { + "text": "Monitor" + }, + "text_636ab6d00a4046aadf62df37": { + "text": "angle-right" + }, + "text_636ab6d00a4046aadf62df3b": { + "text": "Settings" + }, + "text_636ab6d00a4046aadf62df3f": { + "text": "bolt" + }, + "text_636ab6d00a4046aadf62df43": { + "text": "Getting started" + }, + "text_636ab6d00a4046aadf62df47": { + "text": "book-open-cover" + }, + "text_636ab6d00a4046aadf62df4d": { + "text": "Docs & Support" + }, + "text_636ab6d00a4046aadf62df4f": { + "text": "Add source" + }, + "text_636ab6d00a4046aadf62df59": { + "text": "Sources" + }, + "text_636ab6d00a4046aadf62df63": { + "text": "Source" + }, + "text_636ab6d00a4046aadf62df6f": { + "text": "sort" + }, + "text_636ab6d00a4046aadf62df71": { + "text": "search" + }, + "text_636ab6d00a4046aadf62df73": { + "text": "Status" + }, + "text_636ab6d00a4046aadf62df75": { + "text": "filter" + }, + "text_636ab6d00a4046aadf62df77": { + "text": "Destinations" + }, + "text_636ab6d00a4046aadf62df79": { + "text": "sort" + }, + "text_636ab6d00a4046aadf62df7d": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df81": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62df85": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62df89": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df8b": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62df8d": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62df8f": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df93": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62df97": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62df9b": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df9f": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfa5": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfa7": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfa9": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfad": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfb1": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfb3": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfb7": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfb9": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfbb": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfbf": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfc1": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfc3": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfc5": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfd3": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfd7": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfd9": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfdb": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfdf": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfe1": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfe3": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfe5": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfe9": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfeb": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfef": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dff3": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dff5": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dffb": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dffd": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62e001": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62e005": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62e009": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62e00d": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62e011": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62e015": { + "text": "Details" + } + } + }, + "frame_636ab6d00a4046aadf62deef": { + "frameName": "Event promo plan expiring modal", + "blocks": {}, + "otherText": { + "text_636ab6d00a4046aadf62defb": { + "text": "Your plan is set to change from 5M events/month to 1M events/month on Dec. 31. Learn more" + }, + "text_636ab6d00a4046aadf62defd": { + "text": "circle-info" + }, + "text_636ab6d00a4046aadf62df07": { + "text": "xmark" + }, + "text_636ab6d00a4046aadf62df09": { + "text": "arrow-left-from-line" + }, + "text_636ab6d00a4046aadf62df0d": { + "text": "Workspace" + }, + "text_636ab6d00a4046aadf62df0f": { + "text": "Acme Corp." + }, + "text_636ab6d00a4046aadf62df11": { + "text": "angle-right" + }, + "text_636ab6d00a4046aadf62df15": { + "text": "Directory" + }, + "text_636ab6d00a4046aadf62df17": { + "text": "Connect" + }, + "text_636ab6d00a4046aadf62df1f": { + "text": "angle-down" + }, + "text_636ab6d00a4046aadf62df23": { + "text": "Connections" + }, + "text_636ab6d00a4046aadf62df25": { + "text": "Sources" + }, + "text_636ab6d00a4046aadf62df2b": { + "text": "Destinations" + }, + "text_636ab6d00a4046aadf62df2f": { + "text": "Enhance" + }, + "text_636ab6d00a4046aadf62df33": { + "text": "angle-right" + }, + "text_636ab6d00a4046aadf62df35": { + "text": "Monitor" + }, + "text_636ab6d00a4046aadf62df39": { + "text": "angle-right" + }, + "text_636ab6d00a4046aadf62df3d": { + "text": "Settings" + }, + "text_636ab6d00a4046aadf62df41": { + "text": "bolt" + }, + "text_636ab6d00a4046aadf62df45": { + "text": "Getting started" + }, + "text_636ab6d00a4046aadf62df49": { + "text": "book-open-cover" + }, + "text_636ab6d00a4046aadf62df4b": { + "text": "Docs & Support" + }, + "text_636ab6d00a4046aadf62df51": { + "text": "Add source" + }, + "text_636ab6d00a4046aadf62df53": { + "text": "Sources" + }, + "text_636ab6d00a4046aadf62df55": { + "text": "Source" + }, + "text_636ab6d00a4046aadf62df57": { + "text": "sort" + }, + "text_636ab6d00a4046aadf62df5b": { + "text": "search" + }, + "text_636ab6d00a4046aadf62df5d": { + "text": "Status" + }, + "text_636ab6d00a4046aadf62df5f": { + "text": "filter" + }, + "text_636ab6d00a4046aadf62df61": { + "text": "Destinations" + }, + "text_636ab6d00a4046aadf62df65": { + "text": "sort" + }, + "text_636ab6d00a4046aadf62df67": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df69": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62df6b": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62df6d": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df7b": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62df7f": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62df83": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df87": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62df91": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62df95": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df99": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62df9d": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfa1": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfa3": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfab": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfaf": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfb5": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfbd": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfc7": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfc9": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfcb": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfcd": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfcf": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfd1": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfd5": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfdd": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfe7": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfed": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dff1": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dff7": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dff9": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfff": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62e003": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62e007": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62e00b": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62e00f": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62e013": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62e016": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62e018": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62e01a": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62e01c": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62e01e": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62e020": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62e022": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62e025": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62e028": { + "text": "Your Promotional Offer is Expiring" + }, + "text_636ab6d00a4046aadf62e02a": { + "text": "We hope you’ve been enjoying your current promotional plan!\n\nThis promotion will be ending December 31, 2022, and your event limit will change from 5 million to 1 million events.\n\nNothing is needed on your end, however, we recently added a “Starter” plan with new pricing, and recommend making sure you are on the best plan to fit your needs after your current promotion expires." + }, + "text_636ab6d00a4046aadf62e02d": { + "text": "Close" + }, + "text_636ab6d00a4046aadf62e02f": { + "text": "Explore plans" + } + } + } + } + } +} \ No newline at end of file diff --git a/rudder-alerta-enrichment-plugin/ditto/text.json b/rudder-alerta-enrichment-plugin/ditto/text.json new file mode 100644 index 000000000..34e069de0 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/ditto/text.json @@ -0,0 +1,2095 @@ +{ + "projects": { + "project_630f9ed947a50a5d161c8b30": { + "project_id": "630f9ed947a50a5d161c8b30", + "frames": { + "frame_630f9ed9913de551b054b2d3": { + "frameName": "Souce Notification Settings - Admin, Disabled", + "blocks": { + "toggle-settings": { + "text_630f9ed9913de551b054b52b": { + "text": "Enable notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b531": { + "text": "Allow members to subscribe to notifications for this source", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b537": { + "text": "Notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b53d": { + "text": "Subscribe to email alerts for critical data delivery issues. Manage your alerts and subscriptions list in Notification settings.", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b578": { + "text": "You must first enable notifications for this source", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_630f9ed9913de551b054b2d2": { + "frameName": "Souce Notification Settings - Admin, Enabled", + "blocks": { + "toggle-settings": { + "text_630f9ed9913de551b054b4ab": { + "text": "Enable notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4b1": { + "text": "Allow members to subscribe to notifications for this source", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4bf": { + "text": "Notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4c5": { + "text": "Subscribe to email alerts for critical data delivery issues. Manage your alerts and subscriptions list in Notification settings.", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_630f9ed9913de551b054b2d4": { + "frameName": "Souce Notification Settings - Non-admin, Disabled", + "blocks": { + "toggle-settings": { + "text_630f9ed9913de551b054b585": { + "text": "Notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b58b": { + "text": "Subscribe to email alerts for critical data delivery issues. Manage your alerts and subscriptions list in Notification settings.", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b5b0": { + "text": "An admin must first enable notifications for this source", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_630f9ed9913de551b054b2d6": { + "frameName": "Destination Notification Settings - Admin, Disabled", + "blocks": { + "toggle-settings": { + "text_630f9ed9913de551b054b564": { + "text": "Enable notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b56c": { + "text": "Allow members to subscribe to notifications for this destination", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b5a5": { + "text": "You must first enable notifications for this destination", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_630f9ed9913de551b054b2d5": { + "frameName": "Destination Notification Settings - Admin, Enabled", + "blocks": { + "toggle-settings": { + "text_630f9ed9913de551b054b4b7": { + "text": "Enable notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4cb": { + "text": "Allow members to subscribe to notifications for this destination", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4e1": { + "text": "Notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4f4": { + "text": "Subscribe to email alerts for critical data delivery issues. Manage your alerts and subscriptions list in Notification settings.", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_630f9ed9913de551b054b2d7": { + "frameName": "Destination Notification Settings - Non-admin, Disabled", + "blocks": { + "toggle-settings": { + "text_630f9ed9913de551b054b49f": { + "text": "Notifications", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4a9": { + "text": "Subscribe to email alerts for critical data delivery issues. Manage your alerts and subscriptions list in Notification settings.", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b4f1": { + "text": "An admin must first enable notifications for this destination", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_630f9ed9913de551b054b2d8": { + "frameName": "Manage Notifications - Email Toggle", + "blocks": { + "settings": { + "text_630f9ed9913de551b054b412": { + "text": "Data delivery alerts", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b418": { + "text": "Receive email alerts for critical data delivery issues.", + "status": "FINAL" + }, + "text_6328e6392a50c243b9354350": { + "text": "Learn more", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b432": { + "text": "Email alerts", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b444": { + "text": "kland@rudderstack.com", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b462": { + "text": "2 Subscription(s)", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b44a": { + "text": "Manage subscriptions", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_630f9ed9913de551b054b2d9": { + "frameName": "Manage Notifications - Subscription List", + "blocks": { + "subscriptions": { + "text_630f9ed9913de551b054b5b1": { + "text": "Manage subscriptions", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b554": { + "text": "Receive data delivery alerts for subscribed sources.", + "variants": { + "list---destinations": { + "text": "Receive data delivery alerts for subscribed destinations." + }, + "list---warehouses": { + "text": "Receive data delivery alerts for subscribed warehouse destinations." + } + }, + "status": "FINAL" + }, + "text_630f9ed9913de551b054b566": { + "text": "Source subscribed", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b56e": { + "text": "Name", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b57d": { + "text": "Subscribed", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b583": { + "text": "Source name", + "status": "FINAL" + }, + "text_630f9ed9913de551b054b58f": { + "text": "Source name", + "status": "FINAL" + } + } + }, + "otherText": {} + }, + "frame_data_delivery_alert": { + "frameName": "Data Delivery Alert", + "blocks": { + "alert-copy": { + "body_heading_old": { + "text": "[Email Body Title] E.g., Event Volume Drop", + "variants": { + "event-volume-drops": { + "text": "Event Volume Drop" + }, + "transformation-error": { + "text": "Transformation Error" + } + }, + "status": "REVIEW", + "notes": "Title in the email body" + }, + "greeting_old": { + "text": "[Greeting] Hello {{customer}} Team", + "variants": { + "event-volume-drops": { + "text": "Hello {{customer}} Team" + } + }, + "status": "WIP", + "notes": "Greeting line in email body", + "variables": { + "customer": { + "example": "Demo Customer", + "__type": "string" + } + } + }, + "body_old": { + "text": "[Email Body] E.g., “We’ve detected a recent drop in event volume of greater than 25% (vs. the last 7 days) from {{source}} and recommend looking into this issue further.”", + "variants": { + "event-volume-drops": { + "text": "We’ve detected a recent drop in event volume of greater than 25% (vs. the last 7 days) from {{source}} and recommend looking into this issue further." + }, + "delivery-lag": { + "text": "[Email Body] E.g., “We’ve detected a recent drop in event volume of greater than 25% (vs. the last 7 days) {{destination_wh}} and recommend looking into this issue further.”", + "variables": { + "destination_wh": { + "example": "Demo WH Destination", + "__type": "string" + } + } + } + }, + "status": "WIP", + "notes": "Email body", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "", + "__type": "string" + } + } + }, + "cta_button_link_old": { + "text": "[CTA Location / Resource]", + "variants": { + "event-volume-drops": { + "text": "{{cp_base_url_old}}/sources/{{source_id_old}}?tab=Events", + "variables": { + "cp_base_url_old": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "source_id_old": { + "example": "abcde", + "__type": "string" + } + } + } + }, + "status": "WIP", + "notes": "[CTA Button Link] This will be a dynamic field to insert the location or resource that triggered the alert. We can take the user to events tab of the affected source for event volume drop case" + }, + "cta_button_text_old": { + "text": "[CTA Button] E.g., View Events for {{source}}", + "variants": { + "event-volume-drops": { + "text": "View Events from {{source}}" + } + }, + "status": "WIP", + "notes": "CTA Button Text", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "", + "__type": "string" + } + } + }, + "signature_old": { + "text": "[RudderStack Signature]", + "variants": { + "event-volume-drops": { + "text": "RudderStack Team" + } + }, + "status": "WIP", + "notes": "RudderStack Signature" + } + } + }, + "otherText": { + "text_631771ab9d5a185c751a2674": { + "text": "shield-halved#" + }, + "text_631771ab9d5a185c751a2676": { + "text": "shield-halved##" + }, + "text_631771ab9d5a185c751a2684": { + "text": "©2022 RudderStack" + }, + "text_631771ab9d5a185c751a2686": { + "text": "View in Browser" + } + } + }, + "frame_631e3e715a90787937342451": { + "frameName": "Transformation Notification Settings - Admin, Enabled", + "blocks": {}, + "otherText": { + "text_631e3e715a90787937342464": { + "text": "arrow-left-from-line" + }, + "text_631e3e715a9078793734246a": { + "text": "Acme Corp." + }, + "text_631e3e715a90787937342470": { + "text": "john@rudderstack.com" + }, + "text_631e3e715a90787937342478": { + "text": "angle-right" + }, + "text_631e3e715a9078793734247e": { + "text": "Directory" + }, + "text_631e3e715a90787937342484": { + "text": "Connect" + }, + "text_631e3e715a9078793734248a": { + "text": "angle-right" + }, + "text_631e3e715a90787937342490": { + "text": "Enhance" + }, + "text_631e3e715a90787937342496": { + "text": "angle-down" + }, + "text_631e3e715a9078793734249c": { + "text": "Transformations" + }, + "text_631e3e715a907879373424a2": { + "text": "Models" + }, + "text_631e3e715a907879373424a8": { + "text": "Audiences" + }, + "text_631e3e715a907879373424ae": { + "text": "Monitor" + }, + "text_631e3e715a907879373424b4": { + "text": "angle-right" + }, + "text_631e3e715a907879373424ba": { + "text": "Settings" + }, + "text_631e3e715a907879373424c0": { + "text": "bolt" + }, + "text_631e3e715a907879373424c6": { + "text": "Getting started" + }, + "text_631e3e715a907879373424cc": { + "text": "book-open-cover" + }, + "text_631e3e715a907879373424d2": { + "text": "Docs & Support" + }, + "text_631e3e715a907879373424d8": { + "text": "All transformations" + }, + "text_631e3e715a907879373424de": { + "text": "arrow-left" + }, + "text_631e3e715a907879373424e4": { + "text": "/" + }, + "text_631e3e715a907879373424ea": { + "text": "Test6" + }, + "text_631e3e715a907879373424f0": { + "text": "Test 6" + }, + "text_631e3e715a907879373424f6": { + "text": "Description displayed here" + }, + "text_631e3e715a907879373424fc": { + "text": "Live events" + }, + "text_631e3e715a90787937342502": { + "text": "Transformation" + }, + "text_631e3e715a90787937342508": { + "text": "Connections" + }, + "text_631e3e715a9078793734250e": { + "text": "Settings" + }, + "text_631e3e715a90787937342514": { + "text": "General info" + }, + "text_631e3e715a9078793734251a": { + "text": "These are the basic details needed to set up your transformation." + }, + "text_631e3e715a90787937342520": { + "text": "Transforamtion name" + }, + "text_631e3e715a90787937342526": { + "text": "Test 6" + }, + "text_631e3e715a9078793734252c": { + "text": "Transformation description (optional)" + }, + "text_631e3e715a90787937342532": { + "text": "Description of audience here" + }, + "text_631e3e715a90787937342536": { + "text": "pencil" + }, + "text_63288c4532871c3a8efb0678": { + "text": "Notifications" + }, + "text_63288c4532871c3a8efb067a": { + "text": "Enable notifications" + }, + "text_63288c4532871c3a8efb067c": { + "text": "Turn on notifications for this transformation for everyone" + }, + "text_63288c4532871c3a8efb067e": { + "text": "check" + }, + "text_63288c4532871c3a8efb0680": { + "text": "Notifications" + }, + "text_63288c4532871c3a8efb0682": { + "text": "Receive data-delivery alerts. You can manage these in the “subscription” list within Notification settings." + }, + "text_6328bf8f664f6c2de14e2aba": { + "text": "xmark" + }, + "text_631e3e715a90787937342552": { + "text": "Danger zone" + }, + "text_631e3e715a90787937342556": { + "text": "radiation" + }, + "text_631e3e715a9078793734255a": { + "text": "Permanently delete transformation" + }, + "text_631e3e715a90787937342560": { + "text": "Once confirmed, this operation can't be undone!" + }, + "text_631e3e715a90787937342565": { + "text": "trash-can" + }, + "text_631e3e715a90787937342569": { + "text": "Delete" + } + } + }, + "frame_631e3e715a9078793734244d": { + "frameName": "Transformation Notification Settings - Admin, Disabled", + "blocks": { + "toggle-settings": { + "text_631e3e715a90787937342538": { + "text": "Enable notifications", + "status": "FINAL" + }, + "text_631e3e715a9078793734253e": { + "text": "Turn on notifications for this transformation for everyone" + }, + "text_631e3e715a90787937342544": { + "text": "Notifications", + "status": "FINAL" + }, + "text_631e3e715a9078793734254a": { + "text": "Receive data-delivery alerts. You can manage these in the “subscription” list within Notification settings." + } + } + }, + "otherText": { + "text_631e3e715a90787937342460": { + "text": "arrow-left-from-line" + }, + "text_631e3e715a90787937342466": { + "text": "Acme Corp." + }, + "text_631e3e715a9078793734246c": { + "text": "john@rudderstack.com" + }, + "text_631e3e715a90787937342472": { + "text": "angle-right" + }, + "text_631e3e715a90787937342476": { + "text": "Directory" + }, + "text_631e3e715a9078793734247c": { + "text": "Connect" + }, + "text_631e3e715a90787937342482": { + "text": "angle-right" + }, + "text_631e3e715a90787937342488": { + "text": "Enhance" + }, + "text_631e3e715a9078793734248e": { + "text": "angle-down" + }, + "text_631e3e715a90787937342494": { + "text": "Transformations" + }, + "text_631e3e715a9078793734249a": { + "text": "Models" + }, + "text_631e3e715a907879373424a0": { + "text": "Audiences" + }, + "text_631e3e715a907879373424a6": { + "text": "Monitor" + }, + "text_631e3e715a907879373424ac": { + "text": "angle-right" + }, + "text_631e3e715a907879373424b2": { + "text": "Settings" + }, + "text_631e3e715a907879373424b8": { + "text": "bolt" + }, + "text_631e3e715a907879373424be": { + "text": "Getting started" + }, + "text_631e3e715a907879373424c4": { + "text": "book-open-cover" + }, + "text_631e3e715a907879373424ca": { + "text": "Docs & Support" + }, + "text_631e3e715a907879373424d0": { + "text": "All transformations" + }, + "text_631e3e715a907879373424d6": { + "text": "arrow-left" + }, + "text_631e3e715a907879373424dc": { + "text": "/" + }, + "text_631e3e715a907879373424e2": { + "text": "Test6" + }, + "text_631e3e715a907879373424e8": { + "text": "Test 6" + }, + "text_631e3e715a907879373424ee": { + "text": "Description displayed here" + }, + "text_631e3e715a907879373424f4": { + "text": "Live events" + }, + "text_631e3e715a907879373424fa": { + "text": "Transformation" + }, + "text_631e3e715a90787937342500": { + "text": "Connections" + }, + "text_631e3e715a90787937342506": { + "text": "Settings" + }, + "text_631e3e715a9078793734250c": { + "text": "General info" + }, + "text_631e3e715a90787937342512": { + "text": "These are the basic details needed to set up your transformation." + }, + "text_631e3e715a90787937342518": { + "text": "Transforamtion name" + }, + "text_631e3e715a9078793734251e": { + "text": "Test 6" + }, + "text_631e3e715a90787937342524": { + "text": "Transformation description (optional)" + }, + "text_631e3e715a9078793734252a": { + "text": "Description of audience here" + }, + "text_63282355352ef745b29f7165": { + "text": "pencil" + }, + "text_63282355352ef745b29f7169": { + "text": "Notifications" + }, + "text_6324dafac4fb2d4b6b651813": { + "text": "xmark" + }, + "text_6324dafac4fb2d4b6b65182e": { + "text": "xmark" + }, + "text_631e3e715a90787937342550": { + "text": "Danger zone" + }, + "text_631e3e715a90787937342558": { + "text": "radiation" + }, + "text_631e3e715a9078793734255e": { + "text": "Permanently delete transformation" + }, + "text_631e3e715a90787937342563": { + "text": "Once confirmed, this operation can't be undone!" + }, + "text_631e3e715a90787937342567": { + "text": "trash-can" + }, + "text_631e3e715a9078793734256a": { + "text": "Delete" + }, + "text_631e3e715a9078793734256c": { + "text": "Notifications for this transformation have been disabled" + } + } + }, + "frame_631e3e715a9078793734244f": { + "frameName": "Transformation Notification Settings - Non-admin, Disabled", + "blocks": { + "toggle-settings": { + "text_631e3e715a9078793734252e": { + "text": "Notifications", + "status": "FINAL" + }, + "text_631e3e715a90787937342534": { + "text": "Receive data-delivery alerts. You can manage these in the “subscription” list within Notification settings." + }, + "text_631e3e715a90787937342562": { + "text": "Notifications for this transformation have been disabled" + } + } + }, + "otherText": { + "text_631e3e715a9078793734245a": { + "text": "arrow-left-from-line" + }, + "text_631e3e715a9078793734245d": { + "text": "Acme Corp." + }, + "text_631e3e715a90787937342462": { + "text": "john@rudderstack.com" + }, + "text_631e3e715a90787937342468": { + "text": "angle-right" + }, + "text_631e3e715a9078793734246e": { + "text": "Directory" + }, + "text_631e3e715a90787937342474": { + "text": "Connect" + }, + "text_631e3e715a9078793734247a": { + "text": "angle-right" + }, + "text_631e3e715a90787937342480": { + "text": "Enhance" + }, + "text_631e3e715a90787937342486": { + "text": "angle-down" + }, + "text_631e3e715a9078793734248c": { + "text": "Transformations" + }, + "text_631e3e715a90787937342492": { + "text": "Models" + }, + "text_631e3e715a90787937342498": { + "text": "Audiences" + }, + "text_631e3e715a9078793734249e": { + "text": "Monitor" + }, + "text_631e3e715a907879373424a4": { + "text": "angle-right" + }, + "text_631e3e715a907879373424aa": { + "text": "Settings" + }, + "text_631e3e715a907879373424b0": { + "text": "bolt" + }, + "text_631e3e715a907879373424b6": { + "text": "Getting started" + }, + "text_631e3e715a907879373424bc": { + "text": "book-open-cover" + }, + "text_631e3e715a907879373424c2": { + "text": "Docs & Support" + }, + "text_631e3e715a907879373424c8": { + "text": "All transformations" + }, + "text_631e3e715a907879373424ce": { + "text": "arrow-left" + }, + "text_631e3e715a907879373424d4": { + "text": "/" + }, + "text_631e3e715a907879373424da": { + "text": "Test6" + }, + "text_631e3e715a907879373424e0": { + "text": "Test 6" + }, + "text_631e3e715a907879373424e6": { + "text": "Description displayed here" + }, + "text_631e3e715a907879373424ec": { + "text": "Live events" + }, + "text_631e3e715a907879373424f2": { + "text": "Transformation" + }, + "text_631e3e715a907879373424f8": { + "text": "Connections" + }, + "text_631e3e715a907879373424fe": { + "text": "Settings" + }, + "text_63282355352ef745b29f7167": { + "text": "General info" + }, + "text_63282355352ef745b29f716a": { + "text": "These are the basic details needed to set up your transformation." + }, + "text_63282355352ef745b29f716c": { + "text": "Transforamtion name" + }, + "text_63282355352ef745b29f716e": { + "text": "Test 6" + }, + "text_63282355352ef745b29f7170": { + "text": "Transformation description (optional)" + }, + "text_63282355352ef745b29f7172": { + "text": "Description of audience here" + }, + "text_63282355352ef745b29f7174": { + "text": "pencil" + }, + "text_6324dafac4fb2d4b6b651815": { + "text": "xmark" + }, + "text_631e3e715a9078793734253a": { + "text": "Danger zone" + }, + "text_631e3e715a90787937342540": { + "text": "radiation" + }, + "text_631e3e715a90787937342546": { + "text": "Permanently delete transformation" + }, + "text_631e3e715a9078793734254c": { + "text": "Once confirmed, this operation can't be undone!" + }, + "text_631e3e715a90787937342554": { + "text": "trash-can" + }, + "text_631e3e715a9078793734255c": { + "text": "Delete" + } + } + }, + "frame_SES_Alert": { + "frameName": "Current Amazon SES Email Template", + "blocks": {}, + "otherText": { + "subject": { + "text": "[Error Type] | {{source}}", + "variants": { + "event-volume-drops": { + "text": "Event Volume Drop Warning | {{source}}", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "", + "__type": "string" + } + } + }, + "delivery-error": { + "text": "Delivery Error | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "discards": { + "text": "Data Type Mismatch | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "invalid-json": { + "text": "Invalid JSON | {{source}}", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "", + "__type": "string" + } + } + }, + "tracking-plan-event-drops": { + "text": "Event Dropped by Tracking Plan | {{source}}", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "", + "__type": "string" + } + } + }, + "transformation-error": { + "text": "Transformation Error | {{transformation}}", + "variables": { + "transformation": { + "example": "Demo Transformation", + "__type": "string" + } + } + }, + "delivery-error---wh-destination": { + "text": "Delivery Error | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "delivery-lag---wh-destination": { + "text": "Delivery Lag | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "delivery-lag---cloud-destination": { + "text": "Delivery Lag | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "badris-notification": { + "text": "Badri’s Error | {{source}}", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "", + "__type": "string" + } + } + }, + "warehouse-column-count": { + "text": "Delivery warning | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "event-volume-drop-destination": { + "text": "Event Volume Drop Warning | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "warehouse-column-changes": { + "text": "Warehouse columns changes | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "integrations-data-validation": { + "text": "Data Validation Errors | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "integrations-network-aborted-unauthorised-": { + "text": "Network Aborted Unauthorized Errors | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "integrations-network-aborted-instrumentation": { + "text": "Network Aborted Instrumentation Errors | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "integrations-router-aborted-delivery": { + "text": "Router Aborted Delivery | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "partial-row-failures": { + "text": "Partial Row Failures | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "fatal-syncs": { + "text": "Fatal Syncs | {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "fallback": "", + "__type": "string" + } + } + } + }, + "status": "FINAL", + "notes": "Subject line of email", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "", + "__type": "string" + } + } + }, + "body_heading": { + "text": "[Error Type]", + "variants": { + "event-volume-drops": { + "text": "Event Volume Drop Warning" + }, + "delivery-error": { + "text": "Delivery Error" + }, + "discards": { + "text": "Data Type Mismatch" + }, + "invalid-json": { + "text": "Invalid JSON" + }, + "tracking-plan-event-drops": { + "text": "Event Dropped by Tracking Plan" + }, + "transformation-error": { + "text": "Transformation Error" + }, + "delivery-error---wh-destination": { + "text": "Delivery Error" + }, + "delivery-lag---wh-destination": { + "text": "Delivery Lag" + }, + "delivery-lag---cloud-destination": { + "text": "Delivery Lag" + }, + "warehouse-column-count": { + "text": "Delivery warning" + }, + "event-volume-drop-destination": { + "text": "Event Volume Drop Warning" + }, + "warehouse-column-changes": { + "text": "Action required: Drop outdated columns" + }, + "integrations-network-aborted-unauthorised-": { + "text": "Network Aborted Unauthorized Error" + }, + "integrations-network-aborted-instrumentation": { + "text": "Network Aborted Instrumentation Error" + }, + "integrations-router-aborted-delivery": { + "text": "Router Aborted Delivery" + }, + "integrations-data-validation": { + "text": "Data Validation Error" + }, + "partial-row-failures": { + "text": "Partial Row Failures" + }, + "fatal-syncs": { + "text": "Fatal Syncs" + } + }, + "status": "FINAL" + }, + "greeting": { + "text": "Hi {{customer}} Team,", + "variants": { + "event-volume-drops": { + "text": "Hi {{customer}} Team,", + "variables": { + "customer": { + "example": "Demo Customer", + "__type": "string" + } + } + }, + "event-volume-drop-destination": { + "text": "Hi {{customer}} Team,", + "variables": { + "customer": { + "example": "Demo Customer", + "__type": "string" + } + } + } + }, + "status": "FINAL", + "variables": { + "customer": { + "example": "Demo Customer", + "__type": "string" + } + } + }, + "body": { + "text": "“We’ve detected [error type] from {{source}} and recommend looking into this issue further.”", + "variants": { + "event-volume-drops": { + "text": "We’ve noticed a large drop in your event volume in the last 24 hours. Your event volume dropped more than 25% compared to the last 7 days. We recommend you to look a closer look at {{source}} source.", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "", + "__type": "string" + } + } + }, + "delivery-error": { + "text": "We’ve detected a delivery error with {{destination}} and recommend taking a closer look.", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "discards": { + "text": "We’ve detected a data type mismatch that has resulted in a warehouse discard. We recommend taking a closer look." + }, + "invalid-json": { + "text": "We’ve detected an invalid JSON related to {{source}} and recommend taking a closer look.", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "", + "__type": "string" + } + } + }, + "tracking-plan-event-drops": { + "text": "A tracking plan has caused one or more events to be dropped. We recommend taking a closer look." + }, + "transformation-error": { + "text": "We’ve detected a transformation error with {{transformation}} and recommend taking a closer look.", + "variables": { + "transformation": { + "example": "Demo Transformation", + "__type": "string" + } + } + }, + "delivery-error---wh-destination": { + "text": "We’ve detected a delivery error with {{destination}} and recommend taking a closer look.", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "delivery-lag---wh-destination": { + "text": "We’ve detected a delivery lag with {{destination}} and recommend taking a closer look.", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "delivery-lag---cloud-destination": { + "text": "We’ve detected a delivery lag with {{destination}} and recommend taking a closer look.", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "warehouse-column-count": { + "text": "We’ve noticed that you’re reaching your column limit in your {{tableName}} table.
Your current table has {{currentColumnCount}} columns where only {{columnCountLimit}} are allowed. Exceeding this column limit may result in a data delivery error. Please refer to the RudderStack documentation for managing the number of columns in your Warehouse.", + "variables": { + "tableName": { + "example": "Demo Table", + "__type": "string" + }, + "currentColumnCount": { + "example": 950, + "__type": "number" + }, + "columnCountLimit": { + "example": 1000, + "__type": "number" + } + } + }, + "event-volume-drop-destination": { + "text": "We’ve noticed a large drop in your event volume in the last 24 hours. Your event volume dropped more than 25% compared to the last 7 days. We recommend you to look a closer look at {{destination}} destination.", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "warehouse-column-changes": { + "text": "Warehouse column names are not matching to the destination views as the views are outdated. Recreate your views so that they point to the latest column names and then drop the older columns. Please use the queries in the documentation to drop the columns" + }, + "integrations-data-validation": { + "text": "“We’ve detected [Data Validation] error of type {{errorType}} from {{destination}} with destination id {{destination_id}} and recommend looking into this issue further.”\nPlease find details below:\n- Cluster: {{cluster}}\n- Destination Type: {{destType}}\n- Destination ID: {{destination_id}}\n- Namespace: {{namespace}}\n- Workspace ID: {{workspaceId}}", + "variables": { + "errorType": { + "example": "errorType", + "__type": "string" + }, + "destination": { + "example": "Demo Destination", + "__type": "string" + }, + "destination_id": { + "example": "", + "__type": "string" + }, + "cluster": { + "example": "cluster", + "__type": "string" + }, + "destType": { + "example": "DT", + "__type": "string" + }, + "namespace": { + "example": "Namespace", + "__type": "string" + }, + "workspaceId": { + "example": "WorkspaceID", + "__type": "string" + } + } + }, + "integrations-network-aborted-unauthorised-": { + "text": "“We’ve detected Network Aborted Unauthorized Errors from {{destination}} with destination id {{destination_id}} and recommend looking into this issue further.”\nPlease find details below:\n- Cluster: {{cluster}}\n- Destination Type: {{destType}}\n- Destination ID: {{destination_id}}\n- Namespace: {{namespace}}\n- Workspace ID: {{workspaceId}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + }, + "destination_id": { + "example": "", + "__type": "string" + }, + "cluster": { + "example": "cluster", + "__type": "string" + }, + "destType": { + "example": "DT", + "__type": "string" + }, + "namespace": { + "example": "Namespace", + "__type": "string" + }, + "workspaceId": { + "example": "WorkspaceID", + "__type": "string" + } + } + }, + "integrations-network-aborted-instrumentation": { + "text": "“We’ve detected Network Aborted Instrumentation Errors from {{destination}} with destination id {{destination_id}} and recommend looking into this issue further.”\nPlease find details below:\n- Cluster: {{cluster}}\n- Destination Type: {{destType}}\n- Destination ID: {{destination_id}}\n- Namespace: {{namespace}}\n- Workspace ID: {{workspaceId}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + }, + "destination_id": { + "example": "", + "__type": "string" + }, + "cluster": { + "example": "cluster", + "__type": "string" + }, + "destType": { + "example": "DT", + "__type": "string" + }, + "namespace": { + "example": "Namespace", + "__type": "string" + }, + "workspaceId": { + "example": "WorkspaceID", + "__type": "string" + } + } + }, + "integrations-router-aborted-delivery": { + "text": "“We’ve detected Router Aborted Delivery Errors from {{destination}} with destination id {{destination_id}} and recommend looking into this issue further.”\nPlease find details below:\n- Cluster: {{cluster}}\n- Destination Type: {{destType}}\n- Destination ID: {{destination_id}}\n- Namespace: {{namespace}}\n- Workspace ID: {{workspaceId}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + }, + "destination_id": { + "example": "", + "__type": "string" + }, + "cluster": { + "example": "cluster", + "__type": "string" + }, + "destType": { + "example": "DT", + "__type": "string" + }, + "namespace": { + "example": "Namespace", + "__type": "string" + }, + "workspaceId": { + "example": "WorkspaceID", + "__type": "string" + } + } + }, + "partial-row-failures": { + "text": "We’ve detected partial row failures from {{source}} to {{destination}} and recommend taking a closer look.", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "", + "__type": "string" + }, + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "fatal-syncs": { + "text": "We’ve detected Fatal Syncs from {{source}} to {{destination}} and recommend taking a closer look.", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "", + "__type": "string" + }, + "destination": { + "example": "Demo Destination", + "fallback": "", + "__type": "string" + } + } + } + }, + "status": "FINAL", + "notes": "Email body", + "variables": { + "source": { + "example": "Demo Source", + "fallback": "", + "__type": "string" + } + } + }, + "cta_button_text": { + "text": "Review [Error Type]", + "variants": { + "event-volume-drops": { + "text": "Review Event Volume" + }, + "delivery-error": { + "text": "Review Delivery Error" + }, + "discards": { + "text": "Review Data Type Mismatch" + }, + "invalid-json": { + "text": "Review Invalid JSON" + }, + "tracking-plan-event-drops": { + "text": "Review Tracking Plan" + }, + "transformation-error": { + "text": "Review Transformation" + }, + "delivery-error---wh-destination": { + "text": "Review {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "delivery-lag---wh-destination": { + "text": "Review Delivery Lag" + }, + "delivery-lag---cloud-destination": { + "text": "Review Delivery Lag" + }, + "warehouse-column-count": { + "text": "Review {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "event-volume-drop-destination": { + "text": "Review Event Volume" + }, + "warehouse-column-changes": { + "text": "Review {{destination}}", + "variables": { + "destination": { + "example": "Demo Destination", + "__type": "string" + } + } + }, + "integrations-router-aborted-delivery": { + "text": "Review Router Aborted Delivery Error" + }, + "partial-row-failures": { + "text": "Review Partial Row Failures" + }, + "fatal-syncs": { + "text": "Review Fatal Syncs" + }, + "low-event-volume": { + "text": "Review on RudderStack" + }, + "cloud-destination-latency": { + "text": "Review on RudderStack" + } + }, + "status": "FINAL", + "notes": "Copy for CTA button" + }, + "cta_button_link": { + "text": "[CTA Location / Resource]", + "variants": { + "event-volume-drops": { + "text": "{{cp_base_url}}/sources/{{source_id}}?tab=Events", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "source_id": { + "example": "", + "__type": "string" + } + } + }, + "delivery-error": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Events", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "destination_id": { + "example": "", + "__type": "string" + } + } + }, + "delivery-error---wh-destination": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Syncs", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "destination_id": { + "example": "", + "__type": "string" + } + } + }, + "discards": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Syncs", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "destination_id": { + "example": "", + "__type": "string" + } + } + }, + "invalid-json": { + "text": "{{cp_base_url}}/sources/{{source_id}}?tab=Events", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "source_id": { + "example": "", + "__type": "string" + } + } + }, + "tracking-plan-event-drops": { + "text": "{{cp_base_url}}/sources/{{source_id}}?tab=Events", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "source_id": { + "example": "", + "__type": "string" + } + } + }, + "transformation-error": { + "text": "{{cp_base_url}}/transformations/{{transformation_id}}", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "transformation_id": { + "example": "", + "__type": "string" + } + } + }, + "delivery-lag---wh-destination": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Syncs", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "destination_id": { + "example": "", + "__type": "string" + } + } + }, + "delivery-lag---cloud-destination": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Events", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "destination_id": { + "example": "", + "__type": "string" + } + } + }, + "warehouse-column-count": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Syncs", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "destination_id": { + "example": "", + "__type": "string" + } + } + }, + "event-volume-drop-destination": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Events", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "destination_id": { + "example": "", + "__type": "string" + } + } + }, + "warehouse-column-changes": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Syncs", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "destination_id": { + "example": "", + "__type": "string" + } + } + }, + "integrations-router-aborted-delivery": { + "text": "{{squadcast_link}}/incident/{{incident_id}}" + }, + "partial-row-failures": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Events", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "destination_id": { + "example": "", + "__type": "string" + } + } + }, + "fatal-syncs": { + "text": "{{cp_base_url}}/connections/{{job_id}}?tab=Syncs", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "job_id": { + "example": "", + "__type": "string" + } + } + }, + "low-event-volume": { + "text": "{{cp_base_url}}/sources/{{source_id}}?tab=Events", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "source_id": { + "example": "", + "__type": "string" + } + } + }, + "cloud-destination-latency": { + "text": "{{cp_base_url}}/destinations/{{destination_id}}?tab=Events&graph=Latency", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + }, + "destination_id": { + "example": "", + "__type": "string" + } + } + } + }, + "status": "FINAL", + "notes": "[CTA Button Link] This will be a dynamic field to insert the location or resource that triggered the alert. We can take the user to events tab of the affected source for event volume drop case" + }, + "signature": { + "text": "— RudderStack Team", + "variants": { + "event-volume-drops": { + "text": "— RudderStack Team" + } + }, + "status": "FINAL", + "notes": "Signature" + }, + "manage_alerts": { + "text": "Manage the email alerts you receive in Notification Settings.", + "status": "FINAL" + }, + "manage_alerts_link": { + "text": "{{cp_base_url}}/profile", + "status": "REVIEW", + "variables": { + "cp_base_url": { + "example": "https://app.rudderlabs.com", + "__type": "string" + } + } + } + } + }, + "frame_636ab6d00a4046aadf62deed": { + "frameName": "Announcement banner", + "blocks": {}, + "otherText": { + "text_636ab6d00a4046aadf62def7": { + "text": "Your current promo of 5M events per month is expiring on December 31, 2022. Learn more" + }, + "text_636ab6d00a4046aadf62def9": { + "text": "circle-info" + }, + "text_636ab6d00a4046aadf62deff": { + "text": "xmark" + }, + "text_636ab6d00a4046aadf62df4f": { + "text": "Add source" + }, + "text_636ab6d00a4046aadf62df63": { + "text": "Source" + }, + "text_636ab6d00a4046aadf62df6f": { + "text": "sort" + }, + "text_636ab6d00a4046aadf62df71": { + "text": "search" + }, + "text_636ab6d00a4046aadf62df73": { + "text": "Status" + }, + "text_636ab6d00a4046aadf62df75": { + "text": "filter" + }, + "text_636ab6d00a4046aadf62df79": { + "text": "sort" + }, + "text_636ab6d00a4046aadf62df7d": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df81": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62df85": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62df89": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df8b": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62df8d": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62df8f": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df93": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62df97": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62df9b": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df9f": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfa5": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfa7": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfa9": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfad": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfb1": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfb3": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfb7": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfb9": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfbb": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfbf": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfc1": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfc3": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfc5": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfd3": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfd7": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfd9": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfdb": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfdf": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfe1": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfe3": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfe5": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfe9": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfeb": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfef": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dff3": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dff5": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dffb": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dffd": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62e001": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62e005": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62e009": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62e00d": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62e011": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62e015": { + "text": "Details" + } + } + }, + "frame_636ab6d00a4046aadf62deef": { + "frameName": "Event promo plan expiring modal", + "blocks": {}, + "otherText": { + "text_636ab6d00a4046aadf62defb": { + "text": "Your plan is set to change from 5M events/month to 1M events/month on Dec. 31. Learn more" + }, + "text_636ab6d00a4046aadf62defd": { + "text": "circle-info" + }, + "text_636ab6d00a4046aadf62df07": { + "text": "xmark" + }, + "text_636ab6d00a4046aadf62df09": { + "text": "arrow-left-from-line" + }, + "text_636ab6d00a4046aadf62df0d": { + "text": "Workspace" + }, + "text_636ab6d00a4046aadf62df0f": { + "text": "Acme Corp." + }, + "text_636ab6d00a4046aadf62df11": { + "text": "angle-right" + }, + "text_636ab6d00a4046aadf62df15": { + "text": "Directory" + }, + "text_636ab6d00a4046aadf62df17": { + "text": "Connect" + }, + "text_636ab6d00a4046aadf62df1f": { + "text": "angle-down" + }, + "text_636ab6d00a4046aadf62df23": { + "text": "Connections" + }, + "text_636ab6d00a4046aadf62df25": { + "text": "Sources" + }, + "text_636ab6d00a4046aadf62df2b": { + "text": "Destinations" + }, + "text_636ab6d00a4046aadf62df2f": { + "text": "Enhance" + }, + "text_636ab6d00a4046aadf62df33": { + "text": "angle-right" + }, + "text_636ab6d00a4046aadf62df35": { + "text": "Monitor" + }, + "text_636ab6d00a4046aadf62df39": { + "text": "angle-right" + }, + "text_636ab6d00a4046aadf62df3d": { + "text": "Settings" + }, + "text_636ab6d00a4046aadf62df41": { + "text": "rabbit-running" + }, + "text_636ab6d00a4046aadf62df45": { + "text": "Getting started" + }, + "text_636ab6d00a4046aadf62df49": { + "text": "book-open-cover" + }, + "text_636ab6d00a4046aadf62df4b": { + "text": "Docs & Support" + }, + "text_636ab6d00a4046aadf62df51": { + "text": "Add source" + }, + "text_636ab6d00a4046aadf62df53": { + "text": "Sources" + }, + "text_636ab6d00a4046aadf62df55": { + "text": "Source" + }, + "text_636ab6d00a4046aadf62df57": { + "text": "sort" + }, + "text_636ab6d00a4046aadf62df5b": { + "text": "search" + }, + "text_636ab6d00a4046aadf62df5d": { + "text": "Status" + }, + "text_636ab6d00a4046aadf62df5f": { + "text": "filter" + }, + "text_636ab6d00a4046aadf62df61": { + "text": "Destinations" + }, + "text_636ab6d00a4046aadf62df65": { + "text": "sort" + }, + "text_636ab6d00a4046aadf62df67": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df69": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62df6b": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62df6d": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df7b": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62df7f": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62df83": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df87": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62df91": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62df95": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62df99": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62df9d": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfa1": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfa3": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfab": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfaf": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfb5": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfbd": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfc7": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfc9": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfcb": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfcd": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfcf": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfd1": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfd5": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfdd": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dfe7": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dfed": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dff1": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62dff7": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62dff9": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62dfff": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62e003": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62e007": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62e00b": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62e00f": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62e013": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62e016": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62e018": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62e01a": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62e01c": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62e01e": { + "text": "Details" + }, + "text_636ab6d00a4046aadf62e020": { + "text": "Source name" + }, + "text_636ab6d00a4046aadf62e022": { + "text": "Enabled" + }, + "text_636ab6d00a4046aadf62e025": { + "text": "Details" + }, + "text_63ed7a11cba861469014cd8d": { + "text": "Your Promotional Offer is Expiring" + }, + "text_63ed7a11cba861469014cd8e": { + "text": "We hope you’ve been enjoying your current promotional plan!\n\nThis promotion will be ending December 31, 2022, and your event limit will change from 5 million to 1 million events.\n\nNothing is needed on your end, however, we recently added a “Starter” plan with new pricing, and recommend making sure you are on the best plan to fit your needs after your current promotion expires." + }, + "text_63ed7a11cba861469014cd8f": { + "text": "Close" + }, + "text_63ed7a11cba861469014cd90": { + "text": "Explore plans" + } + } + } + } + } + }, + "exported_at": "2023-12-20T07:46:37.981Z" +} \ No newline at end of file diff --git a/rudder-alerta-enrichment-plugin/requirements.txt b/rudder-alerta-enrichment-plugin/requirements.txt new file mode 100644 index 000000000..7739bbda7 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/requirements.txt @@ -0,0 +1,2 @@ +expiringdict==1.2.1 +requests==2.31.0 diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/__init__.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/__init__.py new file mode 100644 index 000000000..55d25dd0e --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/__init__.py @@ -0,0 +1 @@ +from .rudder_enrichment import RudderEnrichment diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/config_backend_client.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/config_backend_client.py new file mode 100644 index 000000000..72f2eb304 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/config_backend_client.py @@ -0,0 +1,15 @@ +import base64 + +import requests as requests + +from rudder_enrichment.environment import RUDDER_CONFIG_BACKEND_ADMIN_USERNAME, RUDDER_CONFIG_BACKEND_ADMIN_PASSWORD + + +class ConfigBackendClient: + encoded_string = f"{RUDDER_CONFIG_BACKEND_ADMIN_USERNAME}:{RUDDER_CONFIG_BACKEND_ADMIN_PASSWORD}".encode('utf-8') + encoded_header = base64.b64encode(encoded_string).decode('utf-8') + + @staticmethod + def get(url, timeout=60): + return requests.get(url, timeout=timeout, + headers={'Authorization': f'Basic {ConfigBackendClient.encoded_header}'}) diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/environment.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/environment.py new file mode 100644 index 000000000..8f47a170f --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/environment.py @@ -0,0 +1,26 @@ +import os + +try: + from alerta.plugins import app # alerta >= 5.0 +except ImportError: + from alerta.app import app # alerta < 5.0 + +RUDDER_CONFIG_BACKEND_SERVICE_BASE_URL = os.environ.get('RUDDER_CONFIG_BACKEND_SERVICE_BASE_URL') or app.config[ + 'RUDDER_CONFIG_BACKEND_SERVICE_BASE_URL'] +RUDDER_CONFIG_BACKEND_ADMIN_USERNAME = os.environ.get('RUDDER_CONFIG_BACKEND_ADMIN_USERNAME') or app.config[ + 'RUDDER_CONFIG_BACKEND_ADMIN_USERNAME'] +RUDDER_CONFIG_BACKEND_ADMIN_PASSWORD = os.environ.get('RUDDER_CONFIG_BACKEND_ADMIN_PASSWORD') or app.config[ + 'RUDDER_CONFIG_BACKEND_ADMIN_PASSWORD'] +RUDDER_CONFIG_BACKEND_DATA_CACHE_TTL = int( + os.environ.get('RUDDER_CONFIG_BACKEND_DATA_CACHE_TTL') or app.config['RUDDER_CONFIG_BACKEND_DATA_CACHE_TTL']) +RUDDER_CONFIG_BACKEND_CACHE_STORE_MAX_SIZE = int( + os.environ.get('RUDDER_CONFIG_BACKEND_CACHE_STORE_MAX_SIZE') or app.config[ + 'RUDDER_CONFIG_BACKEND_CACHE_STORE_MAX_SIZE'] +) +""" +TODO: Pick the URL based on different "Environment" from which the alert is generated from. +""" +RUDDER_WEB_APP_URL_PREFIX = os.environ.get('RUDDER_WEB_APP_URL_PREFIX') or app.config['RUDDER_WEB_APP_URL_PREFIX'] +PLUGIN_DIR = 'rudder-alerta-enrichment-plugin' +DITTO_JSON_PATH = os.environ.get('DITTO_JSON_PATH') or app.config['DITTO_JSON_PATH'] +ALERT_METADATA_CONFIG_FILE = os.environ.get('ALERT_METADATA_CONFIG_FILE') or app.config['ALERT_METADATA_CONFIG_FILE'] diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment.py new file mode 100644 index 000000000..6fa29520b --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment.py @@ -0,0 +1,204 @@ +import enum +import logging + +from alerta.plugins import PluginBase +from alerta.stats import StatsD +from expiringdict import ExpiringDict + +from rudder_enrichment.config_backend_client import ConfigBackendClient +from rudder_enrichment.environment import RUDDER_CONFIG_BACKEND_CACHE_STORE_MAX_SIZE, \ + RUDDER_CONFIG_BACKEND_DATA_CACHE_TTL, \ + RUDDER_CONFIG_BACKEND_SERVICE_BASE_URL +from rudder_enrichment.rudder_enrichment_models import Source, Destination, Workspace, Transformation +from rudder_enrichment.rudder_enrichment_models.Connection import Connection + +log_object = logging.getLogger('alerta.plugins.rudder_enrichment') + +sources_search_words = ['sourceID=', 'sourceId=', 'source-id=', 'source=', 'source_id='] +destinations_search_words = ['destID=', 'destinationId=', 'destinationID=', 'destination-id=', 'destId=', 'destination_id='] +transformation_search_words = ['transformationId=', 'transformation_id='] + + +class CacheStoreKeys(enum.Enum): + SOURCES = "sources" + DESTINATIONS = "destinations" + WORKSPACE = "workspaces" + TRANSFORMATIONS = "transformations" + + +class CacheStore: + def __init__(self, storage_object_type): + self.storage_object_type: CacheStoreKeys = storage_object_type + self.cache_store = ExpiringDict(max_len=RUDDER_CONFIG_BACKEND_CACHE_STORE_MAX_SIZE, + max_age_seconds=RUDDER_CONFIG_BACKEND_DATA_CACHE_TTL) + + def set_cache_store(self, key): + try: + url = f'{RUDDER_CONFIG_BACKEND_SERVICE_BASE_URL}/admin/{self.storage_object_type.value}/{key}' + with StatsD.stats_client.timer("enrichment_cb_lookup_time"): + r = ConfigBackendClient.get(url) + if r.status_code != 200: + raise Exception(r.text) + if self.storage_object_type == CacheStoreKeys.SOURCES: + dao_object = Source.from_json(r.json()) + elif self.storage_object_type == CacheStoreKeys.DESTINATIONS: + dao_object = Destination.from_json(r.json()) + elif self.storage_object_type == CacheStoreKeys.TRANSFORMATIONS: + dao_object = Transformation.from_json(r.json()) + else: + dao_object = Workspace.from_json(r.json()) + self.cache_store[key] = dao_object + return self.cache_store[key] + except Exception as e: + StatsD.increment("enrichment_cb_lookup_error", 1, + tags={"object_type": self.storage_object_type.value, "object_id": key, + "type": self.storage_object_type.value}) + log_object.error(f"RudderEnrichment: Error setting cache store {e}", exc_info=True) + return None + + def get_or_set(self, key): + try: + return self.cache_store[key] + except KeyError as e: + StatsD.increment("enrichment_cache_miss", 1, tags={"id": key, "type": self.storage_object_type.value}) + return self.set_cache_store(key) + + +class RudderEnrichment(PluginBase): + def __init__(self, name=None): + log_object.info("RudderEnrichment: Initialized") + self.sources_cache = CacheStore(CacheStoreKeys.SOURCES) + self.destinations_cache = CacheStore(CacheStoreKeys.DESTINATIONS) + self.workspaces_cache = CacheStore(CacheStoreKeys.WORKSPACE) + self.transformations_cache = CacheStore(CacheStoreKeys.TRANSFORMATIONS) + super(RudderEnrichment, self).__init__(name) + + @staticmethod + def get_matched_tag_value(tags: list, search_words: list): + for tag in tags: + for search_word in search_words: + if tag.startswith(search_word): + return tag.replace(search_word, '') + + def get_metadata(self, store, key): + if store == CacheStoreKeys.SOURCES: + return self.sources_cache.get_or_set(key) + elif store == CacheStoreKeys.DESTINATIONS: + return self.destinations_cache.get_or_set(key) + elif store == CacheStoreKeys.WORKSPACE: + return self.workspaces_cache.get_or_set(key) + elif store == CacheStoreKeys.TRANSFORMATIONS: + return self.transformations_cache.get_or_set(key) + + def search_connections(self, alert): + enriched = False + source_id = self.get_matched_tag_value(alert.tags, sources_search_words) + destination_id = self.get_matched_tag_value(alert.tags, destinations_search_words) + if source_id and destination_id: + source_metadata: Source = self.get_metadata(CacheStoreKeys.SOURCES, source_id) + destination_metadata: Destination = self.get_metadata(CacheStoreKeys.DESTINATIONS, destination_id) + if source_metadata and destination_metadata: + workspace_metadata: Workspace = self.get_metadata(CacheStoreKeys.WORKSPACE, + source_metadata.workspaceId) + source_metadata.workspace_metadata = workspace_metadata + destination_metadata.workspace_metadata = workspace_metadata + connection_metadata = Connection(source_metadata, destination_metadata) + alert = connection_metadata.enrich_alert(alert) + if workspace_metadata: + alert = workspace_metadata.enrich_alert(alert) + enriched = True + else: + StatsD.stats_client.incr("enrichment_source_cb_lookup_err", 1, + tags={"source_id": source_id, "alert_id": alert.id}) + return alert, enriched + + def search_sources(self, alert): + enriched = False + source_id = self.get_matched_tag_value(alert.tags, sources_search_words) + if source_id: + source_metadata: Source = self.get_metadata(CacheStoreKeys.SOURCES, source_id) + if source_metadata: + workspace_metadata: Workspace = self.get_metadata(CacheStoreKeys.WORKSPACE, + source_metadata.workspaceId) + source_metadata.workspace_metadata = workspace_metadata + alert = source_metadata.enrich_alert(alert) + if workspace_metadata: + alert = workspace_metadata.enrich_alert(alert) + enriched = True + else: + StatsD.stats_client.incr("enrichment_source_cb_lookup_err", 1, + tags={"source_id": source_id, "alert_id": alert.id}) + return alert, enriched + + def search_destinations(self, alert): + enriched = False + destination_id = self.get_matched_tag_value(alert.tags, destinations_search_words) + if destination_id: + destination_metadata: Destination = self.get_metadata(CacheStoreKeys.DESTINATIONS, destination_id) + if destination_metadata: + workspace_metadata: Workspace = self.get_metadata(CacheStoreKeys.WORKSPACE, + destination_metadata.workspaceId) + destination_metadata.workspace_metadata = workspace_metadata + alert = destination_metadata.enrich_alert(alert) + if workspace_metadata: + alert = workspace_metadata.enrich_alert(alert) + enriched = True + else: + StatsD.stats_client.incr("enrichment_destination_cb_lookup_err", 1, + tags={"destination_id": destination_id, "alert_id": alert.id}) + return alert, enriched + + def search_transformations(self, alert): + enriched = False + transformation_id = self.get_matched_tag_value(alert.tags, transformation_search_words) + if transformation_id: + transformation_metadata: Transformation = self.get_metadata(CacheStoreKeys.TRANSFORMATIONS, transformation_id) + if transformation_metadata: + workspace_metadata: Workspace = self.get_metadata(CacheStoreKeys.WORKSPACE, + transformation_metadata.workspaceId) + transformation_metadata.workspace_metadata = workspace_metadata + alert = transformation_metadata.enrich_alert(alert) + if workspace_metadata: + alert = workspace_metadata.enrich_alert(alert) + enriched = True + else: + StatsD.stats_client.incr("enrichment_destination_cb_lookup_err", 1, + tags={"transformation_id": transformation_id, "alert_id": alert.id}) + return alert, enriched + + def enrich_alert(self, alert): + methods = [self.search_connections, self.search_sources, self.search_destinations, self.search_transformations] + + for method in methods: + alert, enriched = method(alert) + if enriched and alert.enriched_data: + return alert + + logging.error(f"RudderEnrichment: failed to enrich alert {alert}") + StatsD.stats_client.incr("enrichment_error", 1, tags={"alert_resource": alert.resource}) + raise RuntimeError(f"RudderEnrichment: Workspace id could not be extracted from sources,destinations,workspace for alert {alert.id}") + + def pre_receive(self, alert, *args, **kwargs): + if alert.repeat: + log_object.debug('RudderEnrichment: skipping enrichment for repeated alert') + return alert + log_object.debug('RudderEnrichment: pre_receive %s', alert) + return self.enrich_alert(alert) + + def post_receive(self, alert, *args, **kwargs): + return alert + + def status_change(self, alert, status, text, *args, **kwargs): + if alert.repeat: + log_object.debug('RudderEnrichment: skipping enrichment for repeated alert') + return alert + + log_object.info("RudderEnrichment: status_change %s %s %s", alert, status, text) + alert.status = status + alert.text = text + + if status == 'expired': + log_object.debug('RudderEnrichment: skipping enrichment for expired alert') + return alert + + return self.enrich_alert(alert) diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Connection.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Connection.py new file mode 100644 index 000000000..47edcd953 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Connection.py @@ -0,0 +1,32 @@ +import logging + +from rudder_enrichment.rudder_enrichment_models import Source, Destination +from rudder_enrichment.rudder_enrichment_models.constants import AlertTargetType +from rudder_enrichment.rudder_enrichment_models.ditto import DittoEnrichmentFactory + + +class Connection: + source_metadata: Source = None + destination_metadata: Destination = None + + def __init__(self, source_metadata, destination_metadata, *args, **kwargs): + self.source_metadata = source_metadata + self.destination_metadata = destination_metadata + + def enrich_alert(self, alert): + alert.customer = self.source_metadata.workspaceId + try: + ditto_enricher = DittoEnrichmentFactory.get_instance( + processed_target_type=AlertTargetType.CONNECTION, + source=self.source_metadata, + destination=self.destination_metadata, + alert_type=alert.resource, + severity=alert.severity, + raw_data=alert.raw_data, + ) + + alert.enriched_data = ditto_enricher.enrich() + except Exception as e: + logging.error(f"RudderEnrichment: Error enriching connection {e}", exc_info=True) + raise RuntimeError(f"RudderEnrichment: Error enriching connection {e}") + return alert diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Destination.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Destination.py new file mode 100644 index 000000000..3e1211860 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Destination.py @@ -0,0 +1,52 @@ +import logging + +from rudder_enrichment.environment import RUDDER_WEB_APP_URL_PREFIX +from rudder_enrichment.rudder_enrichment_models.constants import AlertTargetType +from rudder_enrichment.rudder_enrichment_models.Enrichment import EnrichmentObjects +from rudder_enrichment.rudder_enrichment_models.ditto import DittoEnrichmentFactory + + + +class Destination: + workspace_metadata = None + + def __init__(self, id, name, enabled, config, workspaceId, createdAt, updatedAt, deleted, *args, **kwargs): + self.id = id + self.name = name + self.enabled = enabled + self.config = config + self.workspaceId = workspaceId + self.createdAt = createdAt + self.updatedAt = updatedAt + self.deleted = deleted + self.resource_info = kwargs + self.url = f"{RUDDER_WEB_APP_URL_PREFIX}/destinations/{self.id}" + + def enrich_alert(self, alert): + alert.customer = self.workspaceId + try: + ditto_enricher = DittoEnrichmentFactory.get_instance( + processed_target_type=AlertTargetType.DESTINATION, + destination=self, + alert_type=alert.resource, + severity=alert.severity, + raw_data=alert.raw_data + ) + + if ditto_enricher is not None: + alert.enriched_data = ditto_enricher.enrich() + else: + enrichment_function = getattr(EnrichmentObjects, alert.resource) + alert.enriched_data = enrichment_function(destination_id=self.id, workspace_id=self.workspaceId, + url=self.url, + name=self.name, + severity=alert.severity, + workspace_metadata=self.workspace_metadata) + except Exception as e: + logging.error(f"RudderEnrichment: Error enriching destination {e}", exc_info=True) + raise RuntimeError(f"RudderEnrichment: Error enriching destination {e}") + return alert + + @staticmethod + def from_json(json_dict: dict): + return Destination(**json_dict) diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Enrichment.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Enrichment.py new file mode 100644 index 000000000..41b940217 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Enrichment.py @@ -0,0 +1,133 @@ +import datetime +import logging +import urllib.parse as urlparse +from urllib.parse import urlencode + +from rudder_enrichment.config_backend_client import ConfigBackendClient +from rudder_enrichment.environment import RUDDER_CONFIG_BACKEND_SERVICE_BASE_URL + + +class EnrichmentObjects: + @staticmethod + def get_last_wh_uploads(workspace_id, destination_id, n=10, status=None, timeout=60): + url = f"{RUDDER_CONFIG_BACKEND_SERVICE_BASE_URL}/admin/workspaces/{workspace_id}/uploads?destinationId={destination_id}&limit={n}&offset=0" + if status: + url = f"{url}&status={status}" + try: + response = ConfigBackendClient.get(url, timeout=timeout).json() + if response.status_code != 200: + raise Exception(response.text) + if 'uploads' in response: + return response['uploads'] + return [] + except Exception as e: + logging.error(f"RudderEnrichment: Error fetching warehouse uploads {e}", exc_info=True) + return {"wh_uploads_url": url} + + @staticmethod + def __add_query_params_to_url(url, parameters): + if not isinstance(parameters, dict): + parameters = dict() + implicit_params = {"utm_source": "notisvc", "utm_medium": "email"} + url_parts = list(urlparse.urlparse(url)) + query = dict(urlparse.parse_qsl(url_parts[4])) + query.update({**implicit_params, **parameters}) + url_parts[4] = urlencode(query) + return urlparse.urlunparse(url_parts) + + @staticmethod + def upload_aborted(destination_id, workspace_id, name, url, severity, workspace_metadata=None): + incident_time = datetime.datetime.utcnow().strftime("%d-%b-%y %H:%M") + wh_uploads = EnrichmentObjects.get_last_wh_uploads(workspace_id, destination_id, status='aborted') + try: + first_line = f'Hello {workspace_metadata.company_name or ""} Team' + except Exception as e: + first_line = 'Hello Team' + email_title = f"Warehouse Upload Aborted | {name}" + button_name = f'View {name} syncs' + if severity != 'normal': + email_body = f""" + {first_line},
+ We have been alerted that your {name} warehouse destination has failed syncing.
+ This error occurred at {incident_time} utc.
+ - RudderStack Team + """ + email_body_heading = "Upload Aborted" + button_name = f'View {name} syncs' + else: + email_body = f""" + {first_line},
+ The warehouse destination {name} sync is normal and operational. + - RudderStack Team + """ + email_body_heading = "Upload Sync Normal" + _url = EnrichmentObjects.__add_query_params_to_url(url, {"tab": "Syncs"}) + return {"title": email_title, "body": email_body, "email_button_url": _url, + "email_body_heading": email_body_heading, 'button_name': button_name, + 'metadata': {'wh_uploads': wh_uploads, 'destination_id': destination_id, 'workspace_id': workspace_id}} + + @staticmethod + def proc_num_ut_output_failed_events(transformation_id, workspace_id, name, url, severity, destination_list, workspace_metadata=None): + incident_time = datetime.datetime.utcnow().strftime("%d-%b-%y %H:%M") + + destination_line = '' + if len(destination_list) > 0: + destination_line = f"""
This transformation is connected to the following destinations:
{ ''.join([ f'- {name}
' for name in destination_list ]) }
""" + + email_title = f"Transformation Event Failures | {name}" + button_name = f'View {name} transformation' + if severity != 'normal': + email_body = f""" + Hi,
+ We have observed that the following transformation has caused some of your events to fail: {name}
{destination_line} + This failure occurred on {incident_time} UTC.
+ """ + email_body_heading = "User Transformation" + button_name = f'View {name} Transformation' + else: + email_body = f""" + Hi,

+ The user transformation {name} sync is normal and operational. + - RudderStack Team + """ + email_body_heading = "Events flow is back to Normal" + return {"title": email_title, "body": email_body, "email_button_url": url, + "email_body_heading": email_body_heading, 'button_name': button_name, + 'metadata': {'workspace_id': workspace_id}} + + @staticmethod + def warehouse_load_table_column_count(destination_id, workspace_id, name, url, severity, workspace_metadata=None): + incident_time = datetime.datetime.utcnow().strftime("%d-%b-%y %H:%M") + try: + first_line = f'Hello {workspace_metadata.company_name or ""} Team' + except Exception as e: + first_line = 'Hello Team' + email_title = f"Warehouse Column Count | {name}" + button_name = f'View {name} destination' + doc_url = 'https://www.rudderstack.com/docs/destinations/warehouse-destinations/json-column-support/' + if severity != 'normal': + email_body = f""" + {first_line},
+ We have been alerted that your {name} destination has reached the column count threshold.
+ This occurred at {incident_time} utc.

+ Please check if this is expected. If not, here are a few recommendations to avoid sync failures + in the future:
+ 1. Clean up columns that are not necessary - this will help us add new columns as necessary.
+ 2. If you have any JSON objects with dynamic properties in your event payload, flattening them could + effectively cause this situation to arise. You might want to instrument your events to avoid flattening + such JSON objects by following this doc here. +

+ - RudderStack Team + """ + email_body_heading = "Warehouse Column Count" + button_name = f'View {name} destination' + else: + email_body = f""" + {first_line},
+ The warehouse destination {name} column count threshold is normal. + - RudderStack Team + """ + email_body_heading = "Warehouse Column Count Normal" + return {"title": email_title, "body": email_body, "email_button_url": url, + "email_body_heading": email_body_heading, 'button_name': button_name, + 'metadata': {'destination_id': destination_id, 'workspace_id': workspace_id}} diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Source.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Source.py new file mode 100644 index 000000000..3f2a3bb3d --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Source.py @@ -0,0 +1,47 @@ +import logging + +from rudder_enrichment.environment import RUDDER_WEB_APP_URL_PREFIX +from rudder_enrichment.rudder_enrichment_models.constants import AlertTargetType +from rudder_enrichment.rudder_enrichment_models.Enrichment import EnrichmentObjects +from rudder_enrichment.rudder_enrichment_models.ditto import DittoEnrichmentFactory + +class Source: + def __init__(self, id, name, writeKey, enabled, config, workspaceId, createdAt, deleted, *args, **kwargs): + self.id = id + self.name = name + self.writeKey = writeKey + self.enabled = enabled + self.config = config + self.workspaceId = workspaceId + self.createdAt = createdAt + self.deleted = deleted + self.resource_info = kwargs + self.url = f"{RUDDER_WEB_APP_URL_PREFIX}/sources/{self.id}" + + def enrich_alert(self, alert): + alert.customer = self.workspaceId + try: + ditto_enricher = DittoEnrichmentFactory.get_instance( + processed_target_type=AlertTargetType.SOURCE, + source=self, + alert_type=alert.resource, + severity=alert.severity, + raw_data=alert.raw_data + ) + if ditto_enricher is not None: + alert.enriched_data = ditto_enricher.enrich() + else: + enrichment_function = getattr(EnrichmentObjects, alert.resource) + alert.enriched_data = enrichment_function(source_id=self.id, workspace_id=self.workspaceId, + url=self.url, + name=self.name, + severity=alert.severity, + workspace_metadata=self.workspace_metadata) + except Exception as e: + logging.error(f"RudderEnrichment: Error enriching source {e}", exc_info=True) + raise RuntimeError(f"RudderEnrichment: Error enriching source {e}") + return alert + + @staticmethod + def from_json(json_dict: dict): + return Source(**json_dict) diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Transformation.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Transformation.py new file mode 100644 index 000000000..6e8d435ea --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Transformation.py @@ -0,0 +1,57 @@ +import logging + +from rudder_enrichment.environment import RUDDER_WEB_APP_URL_PREFIX +from rudder_enrichment.rudder_enrichment_models.constants import AlertTargetType +from rudder_enrichment.rudder_enrichment_models.Enrichment import EnrichmentObjects +from rudder_enrichment.rudder_enrichment_models.ditto import DittoEnrichmentFactory + + +class Transformation: + workspace_metadata = None + + def __init__(self, id, name, description, workspaceId, createdAt, updatedAt, codeVersion, destinations=[], *args, **kwargs): + self.id = id + self.name = name + self.description = description + self.workspaceId = workspaceId + self.createdAt = createdAt + self.updatedAt = updatedAt + self.codeVersion = codeVersion + self.destinations = destinations + self.resource_info = kwargs + self.url = f"{RUDDER_WEB_APP_URL_PREFIX}/transformations/{self.id}" + + + def enrich_alert(self, alert): + alert.customer = self.workspaceId + + try: + ditto_enricher = DittoEnrichmentFactory.get_instance( + processed_target_type=AlertTargetType.TRANSFORMATION, + transformation=self, + alert_type=alert.resource, + severity=alert.severity, + raw_data=alert.raw_data + ) + if ditto_enricher is not None: + alert.enriched_data = ditto_enricher.enrich() + else: + + enrichment_function = getattr(EnrichmentObjects, alert.resource) + alert.enriched_data = enrichment_function(transformation_id=self.id, workspace_id=self.workspaceId, + url=self.url, + name=self.name, + severity=alert.severity, + destination_list=self.get_destination_list(self.destinations), + workspace_metadata=self.workspace_metadata) + except Exception as e: + logging.error(f"RudderEnrichment: Error enriching transformation {e}", exc_info=True) + raise RuntimeError(f"RudderEnrichment: Error enriching transformation {e}") + return alert + + def get_destination_list(self, destinations): + return [ dest["name"] for dest in destinations ] + + @staticmethod + def from_json(json_dict: dict): + return Transformation(**json_dict) diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Workspace.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Workspace.py new file mode 100644 index 000000000..d2d6c01e6 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/Workspace.py @@ -0,0 +1,38 @@ +class Workspace: + def __init__(self, id, name, token, owner, organization, *args, **kwargs): + self.id = id + self.name = name + self.token = token + self.owner = owner + self.organization = organization + + def enrich_alert(self, alert): + if not isinstance(alert.enriched_data, dict) and not alert.enriched_data: + alert.enriched_data = {} + alert.enriched_data['admin_email'] = self.admin_email + settings = self.organization['settings'] + is_pro = settings.get('pro', False) + is_enterprise = settings.get('enterprise', False) + is_paid = any([is_pro, is_enterprise]) + is_trail = not is_paid + alert.properties = {"freetrail": is_trail} + return alert + + @property + def company_name(self): + return self.organization['name'] + + @property + def admin_email(self): + try: + return self.owner['email'] + except Exception as e: + return None + + @staticmethod + def from_json(json_dict: dict): + return Workspace(**json_dict) + + @staticmethod + def attach_customer_information(): + pass diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/__init__.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/__init__.py new file mode 100644 index 000000000..e33979e55 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/__init__.py @@ -0,0 +1,4 @@ +from .Destination import Destination +from .Source import Source +from .Workspace import Workspace +from .Transformation import Transformation \ No newline at end of file diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/constants.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/constants.py new file mode 100644 index 000000000..e92b36526 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/constants.py @@ -0,0 +1,8 @@ +from enum import Enum + + +class AlertTargetType(Enum): + SOURCE = 'source' + TRANSFORMATION = 'transformation' + DESTINATION = 'destination' + CONNECTION = 'connection' diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/BaseDittoEnrichment.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/BaseDittoEnrichment.py new file mode 100644 index 000000000..6fe443e96 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/BaseDittoEnrichment.py @@ -0,0 +1,181 @@ +from abc import ABC, abstractmethod +import datetime +import json +import logging +import re + +from rudder_enrichment.environment import RUDDER_WEB_APP_URL_PREFIX +from rudder_enrichment.rudder_enrichment_models.ditto import projects +from rudder_enrichment.rudder_enrichment_models import utils + + +class BaseDittoEnrichment(ABC): + FRAME_NAME = 'frame_SES_Alert' + BLOCK_NAME = 'amazon-ses-template' + + @abstractmethod + def __init__(self, alert_type, ditto_variant_base_name, workspace_id, url, severity, workspace_metadata, raw_data): + self.alert_type = alert_type + + if severity == 'normal': + self.ditto_variant_name = ditto_variant_base_name + '_normal' + raise Exception("Normal state variant not supported") + else: + self.ditto_variant_name = ditto_variant_base_name + + self.workspace_id = workspace_id + self.url = url + self.severity = severity + self.workspace_metadata = workspace_metadata + self.var_values_map = None + self.raw_data = raw_data + + def build_var_values_map(self, **kwargs): + customer_name = None + + try: + customer_name = self.workspace_metadata.company_name + except Exception: + pass + + if customer_name is None: + customer_name = '' + + var_values_map = {'customer': customer_name, 'workspace_id': self.workspace_id, + 'cp_base_url': RUDDER_WEB_APP_URL_PREFIX, 'severity': self.severity} + var_values_map.update(self.extract_metadata_from_raw_data()) + var_values_map.update(kwargs) + + return var_values_map + + def extract_metadata_from_raw_data(self): + metadata = {} + try: + if self.raw_data is not None: + raw_json = json.loads(self.raw_data) + if 'series' in raw_json: + series = raw_json['series'][0] + + if 'columns' in series and 'values' in series: + columns = series['columns'] + values = series['values'][0] + pattern = "m.*[.]" + for (column, value) in zip(columns, values): + # Normalizing column for kapacitor multi-metric-template + normalized_column = re.sub(pattern, '', column) + + metadata[normalized_column] = value + + if 'tags' in series: + metadata.update(series['tags']) + + if 'labels' in raw_json: + metadata.update(raw_json['labels']) + + except Exception as e: + logging.error(f"DittoRudderEnrichment: error extracting metadata {e}", exc_info=True) + return metadata + + + def build_alert_metadata_map(self, **kwargs): + alert_metadata_map = { + 'workspace_id': self.workspace_id, + 'workspace_name': self.workspace_metadata.name, + 'organization_name': self.workspace_metadata.organization.get('name'), + 'organization_id': self.workspace_metadata.organization.get('id'), + 'namespace': self.get_namespace(), + 'plan': self.workspace_metadata.organization.get('billingInfo', {}).get('planName'), + 'alert_name':self.alert_type + } + alert_metadata_map.update(kwargs) + + return alert_metadata_map + + + def get_namespace(self): + namespace = '' + + if self.raw_data is None: + return namespace + + raw_json = json.loads(self.raw_data) + + is_namespace_in_kapacitor_payload = len(raw_json.get('series', [])) > 0 and raw_json.get('series')[0].get('tags', {}).get('namespace') + is_namespace_in_prometheus_payload = raw_json.get('labels', {}).get('namespace') + if is_namespace_in_kapacitor_payload: + namespace = raw_json.get('series')[0].get('tags', {}).get('namespace') + elif is_namespace_in_prometheus_payload: + namespace = raw_json.get('labels', {}).get('namespace') + + return namespace + + + def get_target_name(self): + pass + + def substitute_vars_in_text(self, text: str, ditto_vars_map: dict, var_values_map: dict): + if len(ditto_vars_map) == 0: + return text + + for ditto_var, ditto_values in ditto_vars_map.items(): + if 'Text' in ditto_values and 'URL' in ditto_values: + piece = f'{ditto_values["Text"]}' + else: + piece = var_values_map.get(ditto_var) + + if piece is None: + logging.error(f'DittoRudderEnrichment error: Cannot find value for {ditto_var} for text {text}.') + piece = ditto_vars_map.get(ditto_var, {}).get('Fallback') + + if piece is not None: + text = re.sub('{{' + ditto_var + '}}', str(piece), text) + else: + logging.error(f'DittoRudderEnrichment error: Cannot find fallback value for {ditto_var} for text {text}.') + + return text + + def fetch_component_with_substitutions_and_overrides(self, block: dict, component: str, var_values_map: dict): + text = block[component].get('text') + ditto_vars_map = block[component].get('variables', {}) + override = block[component].get('variants', {}).get(self.ditto_variant_name, {}).get('text') + + if override is not None: + text = override + ditto_vars_map.update(block[component].get('variants', {}).get(self.ditto_variant_name, {}).get('variables', {})) + + return self.substitute_vars_in_text(text, ditto_vars_map, var_values_map) + + def enrich(self): + incident_time = datetime.datetime.utcnow().strftime("%d-%b-%y %H:%M") + var_values_map = self.build_var_values_map(incident_time=incident_time) + block = projects.get_project_data()['frames'][self.__class__.FRAME_NAME]['otherText'] + + greeting = self.fetch_component_with_substitutions_and_overrides(block, 'greeting', var_values_map) + email_subject = self.fetch_component_with_substitutions_and_overrides(block, 'subject', var_values_map) + button_name = self.fetch_component_with_substitutions_and_overrides(block, 'cta_button_text', var_values_map) + button_url = self.fetch_component_with_substitutions_and_overrides(block, 'cta_button_link', var_values_map) + button_url = utils.add_query_params_to_url(button_url, {}) + body = self.fetch_component_with_substitutions_and_overrides(block, 'body', var_values_map) + email_body_heading = self.fetch_component_with_substitutions_and_overrides(block, 'body_heading', var_values_map) + signature = self.fetch_component_with_substitutions_and_overrides(block, 'signature', var_values_map) + notification_settings_text = self.fetch_component_with_substitutions_and_overrides(block, 'manage_alerts', var_values_map) + notification_settings_url = self.fetch_component_with_substitutions_and_overrides(block, 'manage_alerts_link', var_values_map) + notification_settings_url = utils.add_query_params_to_url(notification_settings_url, {}) + + email_body = f""" + {greeting}

+ {body} +

+ {signature} + """ + + return { + 'title': email_subject, + 'body': email_body, + 'email_button_url': button_url, + 'email_body_heading': email_body_heading, + 'button_name': button_name, + 'notification_settings_text': notification_settings_text, + 'notification_settings_url': notification_settings_url, + 'metadata': self.build_alert_metadata_map() + } \ No newline at end of file diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/ConnectionDittoEnrichment.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/ConnectionDittoEnrichment.py new file mode 100644 index 000000000..a0749cd42 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/ConnectionDittoEnrichment.py @@ -0,0 +1,45 @@ +from .BaseDittoEnrichment import BaseDittoEnrichment + +class ConnectionDittoEnrichment(BaseDittoEnrichment): + def __init__(self, alert_type, ditto_variant_base_name, source, source_id, source_deleted, source_info, + destination, destination_id, destination_deleted, destination_info, + workspace_id, url, severity, workspace_metadata, raw_data): + self.source = source + self.source_id = source_id + self.source_deleted = source_deleted + self.destination = destination + self.destination_id = destination_id + self.destination_deleted = destination_deleted + self.source_info = source_info + self.destination_info = destination_info + super().__init__(alert_type, ditto_variant_base_name, workspace_id, url, severity, workspace_metadata, raw_data) + + def get_target_name(self): + return self.destination + + def build_var_values_map(self, **kwargs): + var_values_map = super(ConnectionDittoEnrichment, self).build_var_values_map(**kwargs) + var_values_map['source'] = self.source + var_values_map['source_id'] = self.source_id + var_values_map['destination'] = self.destination + var_values_map['destination_id'] = self.destination_id + + return var_values_map + + def build_alert_metadata_map(self, **kwargs): + alert_metadata_map = super(ConnectionDittoEnrichment, self).build_alert_metadata_map(**kwargs) + alert_metadata_map['source_name'] = self.source + alert_metadata_map['source_id'] = self.source_id + alert_metadata_map['source_definition_id'] = self.source_info.get('sourceDefinition', {}).get('id') + alert_metadata_map['source_definition_name'] = self.source_info.get('sourceDefinition', {}).get('displayName') + + alert_metadata_map['destination_name'] = self.destination + alert_metadata_map['destination_id'] = self.destination_id + alert_metadata_map['destination_definition_id'] = self.destination_info.get('destinationDefinition', {}).get('id') + alert_metadata_map['destination_definition_name'] = self.destination_info.get('destinationDefinition', {}).get('displayName') + alert_metadata_map['category'] = self.destination_info.get('destinationDefinition', {}).get('category') + + alert_metadata_map['resource_type'] = 'connection' + alert_metadata_map['resource_deleted'] = self.source_deleted or self.destination_deleted + + return alert_metadata_map diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/DestinationDittoEnrichment.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/DestinationDittoEnrichment.py new file mode 100644 index 000000000..89601c8d5 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/DestinationDittoEnrichment.py @@ -0,0 +1,31 @@ +from .BaseDittoEnrichment import BaseDittoEnrichment + +class DestinationDittoEnrichment(BaseDittoEnrichment): + def __init__(self, alert_type, ditto_variant_base_name, destination, destination_id, destination_deleted, workspace_id, url, severity, + workspace_metadata, raw_data, resource_info): + self.destination = destination + self.destination_id = destination_id + self.destination_deleted = destination_deleted + self.resource_info = resource_info + super().__init__(alert_type, ditto_variant_base_name, workspace_id, url, severity, workspace_metadata, raw_data) + + def get_target_name(self): + return self.destination + + def build_var_values_map(self, **kwargs): + var_values_map = super(DestinationDittoEnrichment, self).build_var_values_map(**kwargs) + var_values_map['destination'] = self.destination + var_values_map['destination_id'] = self.destination_id + + return var_values_map + + def build_alert_metadata_map(self, **kwargs): + alert_metadata_map = super(DestinationDittoEnrichment, self).build_alert_metadata_map(**kwargs) + alert_metadata_map['resource_type'] = 'destination' + alert_metadata_map['resource_id'] = self.destination_id + alert_metadata_map['name'] = self.destination + alert_metadata_map['resource_deleted'] = self.destination_deleted + alert_metadata_map['resource_definition_id'] = self.resource_info.get('destinationDefinition', {}).get('id') + alert_metadata_map['resource_definition_name'] = self.resource_info.get('destinationDefinition', {}).get('displayName') + alert_metadata_map['category'] = self.resource_info.get('destinationDefinition', {}).get('category') + return alert_metadata_map diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/DittoEnrichmentFactory.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/DittoEnrichmentFactory.py new file mode 100644 index 000000000..57b323b07 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/DittoEnrichmentFactory.py @@ -0,0 +1,91 @@ +from rudder_enrichment.rudder_enrichment_models.constants import AlertTargetType +from .SourceDittoEnrichment import SourceDittoEnrichment +from .TransformationDittoEnrichment import TransformationDittoEnrichment +from .DestinationDittoEnrichment import DestinationDittoEnrichment +from .ConnectionDittoEnrichment import ConnectionDittoEnrichment +from rudder_enrichment.environment import ALERT_METADATA_CONFIG_FILE +import json +import logging + +class DittoEnrichmentFactory: + + @staticmethod + def get_instance(alert_type, processed_target_type, severity, raw_data, source=None, destination=None, transformation=None): + alert_metadata = DittoEnrichmentFactory.get_alert_metadata(alert_name=alert_type) + dittoVariant = alert_metadata.get('dittoVariant') + identified_target_type = alert_metadata.get('resourceType') + + if identified_target_type is None or identified_target_type != processed_target_type.value: + return None + + if identified_target_type == AlertTargetType.CONNECTION.value: + return ConnectionDittoEnrichment( + alert_type=alert_type, + ditto_variant_base_name=dittoVariant, + source=source.name, + source_id=source.id, + source_deleted=source.deleted, + source_info=source.resource_info, + url=source.url, + destination=destination.name, + destination_id=destination.id, + destination_deleted=destination.deleted, + destination_info=destination.resource_info, + workspace_id=source.workspaceId, + workspace_metadata=source.workspace_metadata, + severity=severity, + raw_data=raw_data + ) + elif identified_target_type == AlertTargetType.SOURCE.value: + return SourceDittoEnrichment( + alert_type=alert_type, + ditto_variant_base_name=dittoVariant, + source=source.name, + source_id=source.id, + source_deleted=source.deleted, + workspace_id=source.workspaceId, + url=source.url, + severity=severity, + workspace_metadata=source.workspace_metadata, + raw_data=raw_data, + resource_info=source.resource_info + ) + elif identified_target_type == AlertTargetType.TRANSFORMATION.value: + return TransformationDittoEnrichment( + alert_type=alert_type, + ditto_variant_base_name=dittoVariant, + transformation=transformation.name, + transformation_id=transformation.id, + workspace_id=transformation.workspaceId, + url=transformation.url, + severity=severity, + workspace_metadata=transformation.workspace_metadata, + raw_data=raw_data, + resource_info=transformation.resource_info + ) + elif identified_target_type == AlertTargetType.DESTINATION.value: + return DestinationDittoEnrichment( + alert_type=alert_type, + ditto_variant_base_name=dittoVariant, + destination=destination.name, + destination_id=destination.id, + destination_deleted=destination.deleted, + workspace_id=destination.workspaceId, + url=destination.url, + severity=severity, + workspace_metadata=destination.workspace_metadata, + raw_data=raw_data, + resource_info=destination.resource_info + ) + + return None + + + @staticmethod + def get_alert_metadata(alert_name): + try: + with open(ALERT_METADATA_CONFIG_FILE, 'r') as f: + alert_metadata = json.load(f)['alertMetadata'] + return alert_metadata[alert_name] + except Exception as e: + logging.error(f"Error loading alert metadata; {e}", exc_info=True) diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/SourceDittoEnrichment.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/SourceDittoEnrichment.py new file mode 100644 index 000000000..412a7e744 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/SourceDittoEnrichment.py @@ -0,0 +1,34 @@ +from .BaseDittoEnrichment import BaseDittoEnrichment + +class SourceDittoEnrichment(BaseDittoEnrichment): + def __init__(self, alert_type, ditto_variant_base_name, source, source_id, source_deleted, workspace_id, url, severity, + workspace_metadata, raw_data, resource_info): + self.source = source + self.source_id = source_id + self.source_deleted = source_deleted + self.resource_info = resource_info + super().__init__(alert_type, ditto_variant_base_name, workspace_id, url, severity, workspace_metadata, raw_data) + + def get_target_name(self): + return self.source + + def build_var_values_map(self, **kwargs): + var_values_map = super(SourceDittoEnrichment, self).build_var_values_map(**kwargs) + var_values_map['source'] = self.source + var_values_map['source_id'] = self.source_id + + return var_values_map + + def build_alert_metadata_map(self, **kwargs): + alert_metadata_map = super(SourceDittoEnrichment, self).build_alert_metadata_map(**kwargs) + alert_metadata_map['resource_type'] = 'source' + alert_metadata_map['resource_id'] = self.source_id + alert_metadata_map['name'] = self.source + alert_metadata_map['resource_deleted'] = self.source_deleted + alert_metadata_map['resource_definition_id'] = self.resource_info.get('sourceDefinition', {}).get('id') + alert_metadata_map['resource_definition_name'] = self.resource_info.get('sourceDefinition', {}).get('displayName') + alert_metadata_map['category'] = self.resource_info.get('sourceDefinition', {}).get('category') + + return alert_metadata_map + + diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/TransformationDittoEnrichment.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/TransformationDittoEnrichment.py new file mode 100644 index 000000000..2c51ea7cb --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/TransformationDittoEnrichment.py @@ -0,0 +1,33 @@ +from .BaseDittoEnrichment import BaseDittoEnrichment + + +class TransformationDittoEnrichment(BaseDittoEnrichment): + def __init__(self, alert_type, ditto_variant_base_name, transformation, transformation_id, workspace_id, url, + severity, + workspace_metadata, + raw_data, + resource_info): + self.transformation = transformation + self.transformation_id = transformation_id + self.resource_info = resource_info + super().__init__(alert_type, ditto_variant_base_name, workspace_id, url, severity, workspace_metadata, raw_data) + + def get_target_name(self): + return self.transformation + + def build_var_values_map(self, **kwargs): + var_values_map = super(TransformationDittoEnrichment, self).build_var_values_map(**kwargs) + var_values_map['transformation'] = self.transformation + var_values_map['transformation_id'] = self.transformation_id + + return var_values_map + + def build_alert_metadata_map(self, **kwargs): + alert_metadata_map = super(TransformationDittoEnrichment, self).build_alert_metadata_map(**kwargs) + alert_metadata_map['transformation_id'] = self.transformation_id + + alert_metadata_map['resource_type'] = 'transformation' + alert_metadata_map['resource_id'] = self.transformation_id + alert_metadata_map['name'] = self.transformation + + return alert_metadata_map diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/__init__.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/__init__.py new file mode 100644 index 000000000..29beca41d --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/__init__.py @@ -0,0 +1,5 @@ +from .SourceDittoEnrichment import SourceDittoEnrichment +from .TransformationDittoEnrichment import TransformationDittoEnrichment +from .DestinationDittoEnrichment import DestinationDittoEnrichment + +from .DittoEnrichmentFactory import DittoEnrichmentFactory \ No newline at end of file diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/projects.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/projects.py new file mode 100644 index 000000000..a7aa3e188 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/ditto/projects.py @@ -0,0 +1,36 @@ +from enum import Enum +import json +import logging +import os +from rudder_enrichment.environment import PLUGIN_DIR, DITTO_JSON_PATH + + +class ProjectIdentifier(Enum): + NOTIFICATIONS_AND_ALERTS = 'project_630f9ed947a50a5d161c8b30' + + +projectwise_data = {} +DEFAULT_PROJECT = ProjectIdentifier.NOTIFICATIONS_AND_ALERTS + +def get_all_data(): + global projectwise_data + + if len(projectwise_data) == 0: + try: + with open(DITTO_JSON_PATH, 'r') as f: + projectwise_data = json.load(f)['projects'] + except Exception as e: + logging.error(f"Ditto: Error loading data; {e}", exc_info=True) + + return projectwise_data + + +def get_project_data(project: ProjectIdentifier = None): + data = {} + + try: + data = get_all_data()[DEFAULT_PROJECT.value if project is None else project.value] + except Exception as e: + logging.error(f"Ditto: Error loading {project.name} data; {e}", exc_info=True) + + return data diff --git a/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/utils.py b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/utils.py new file mode 100644 index 000000000..84b5b4d5e --- /dev/null +++ b/rudder-alerta-enrichment-plugin/rudder_enrichment/rudder_enrichment_models/utils.py @@ -0,0 +1,12 @@ +import urllib.parse as urlparse +from urllib.parse import urlencode + +def add_query_params_to_url(url, parameters): + if not isinstance(parameters, dict): + parameters = dict() + implicit_params = {"utm_source": "notisvc", "utm_medium": "email"} + url_parts = list(urlparse.urlparse(url)) + query = dict(urlparse.parse_qsl(url_parts[4])) + query.update({**implicit_params, **parameters}) + url_parts[4] = urlencode(query) + return urlparse.urlunparse(url_parts) \ No newline at end of file diff --git a/rudder-alerta-enrichment-plugin/setup.py b/rudder-alerta-enrichment-plugin/setup.py new file mode 100644 index 000000000..0430a2c32 --- /dev/null +++ b/rudder-alerta-enrichment-plugin/setup.py @@ -0,0 +1,22 @@ +from setuptools import setup, find_packages +setup( + name='rudder-alerta-enrichment-plugin', + version='1.0.0', + packages=['rudder_enrichment', 'rudder_enrichment.rudder_enrichment_models', 'rudder_enrichment.rudder_enrichment_models.ditto'], + url='https://github.com/rudderlabs/rudder-alerta-enrichment-plugin', + license='', + author='Rudderstack', + author_email='varun@rudderstack.com', + description='Rudderstack alerta enrichment plugin to enrich alerts delivered to end users, by adding context to alerts', + include_package_data=True, + install_requires=[ + 'expiringdict==1.2.1', + 'requests==2.26.0' + ], + zip_safe=True, + entry_points={ + 'alerta.plugins': [ + 'rudder_enrichment = rudder_enrichment:RudderEnrichment' + ] + } +)