From ef89c4deeb676450d75423b5886e8d0d6bdf13bb Mon Sep 17 00:00:00 2001 From: Yashasvi Bajpai <33063622+yashasvibajpai@users.noreply.github.com> Date: Thu, 30 Nov 2023 10:02:23 +0530 Subject: [PATCH 1/7] chore: init onboard --- src/features.json | 1 + src/v0/destinations/adobe_analytics/config.js | 1 + .../adobe_analytics/networkHandler.js | 71 +++++++++++++++++++ 3 files changed, 73 insertions(+) create mode 100644 src/v0/destinations/adobe_analytics/networkHandler.js diff --git a/src/features.json b/src/features.json index 224968c99b..848b606b47 100644 --- a/src/features.json +++ b/src/features.json @@ -1,6 +1,7 @@ { "routerTransform": { "ACTIVE_CAMPAIGN": true, + "ADOBE_ANALYTICS": true, "ALGOLIA": true, "CANDU": true, "DELIGHTED": true, diff --git a/src/v0/destinations/adobe_analytics/config.js b/src/v0/destinations/adobe_analytics/config.js index 7a66b32a48..232fe61f7f 100644 --- a/src/v0/destinations/adobe_analytics/config.js +++ b/src/v0/destinations/adobe_analytics/config.js @@ -44,4 +44,5 @@ module.exports = { ECOM_PRODUCT_EVENTS, commonConfig: MAPPING_CONFIG[CONFIG_CATEGORIES.COMMON.name], formatDestinationConfig, + DESTINATION: 'ADOBE_ANALYTICS' }; diff --git a/src/v0/destinations/adobe_analytics/networkHandler.js b/src/v0/destinations/adobe_analytics/networkHandler.js new file mode 100644 index 0000000000..4b8de886e3 --- /dev/null +++ b/src/v0/destinations/adobe_analytics/networkHandler.js @@ -0,0 +1,71 @@ +const { NetworkError } = require('@rudderstack/integrations-lib'); +const { proxyRequest, prepareProxyRequest } = require('../../../adapters/network'); +const { + getDynamicErrorType, + processAxiosResponse, +} = require('../../../adapters/utils/networkUtils'); +const { DESTINATION } = require('./config'); +const { isDefinedAndNotNull, isDefined, isHttpStatusSuccess } = require('../../util'); + +const tags = require('../../util/tags'); + +const responseHandler = (destinationResponse, dest) => { + const message = `[${DESTINATION}] - Request Processed Successfully`; + let { status, reason } = destinationResponse; + const { response } = destinationResponse; + if (status === 204) { + // GA4 always returns a 204 response, other than in case of + // validation endpoint. + status = 200; + } else if ( + status === 200 && + isDefinedAndNotNull(response) && + isDefined(response.validationMessages) + ) { + // for GA4 debug validation endpoint, status is always 200 + // validationMessages[] is empty, thus event is valid + if (response.validationMessages?.length === 0) { + status = 200; + } else { + // Build the error in case the validationMessages[] is non-empty + const { description, validationCode, fieldPath } = response.validationMessages[0]; + throw new NetworkError( + `Validation Server Response Handler:: Validation Error for ${dest} of field path :${fieldPath} | ${validationCode}-${description}`, + status, + { + [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(status), + }, + response?.validationMessages[0]?.description, + ); + } + } + + // if the response from destination is not a success case build an explicit error + if (!isHttpStatusSuccess(status)) { + throw new NetworkError( + `[GA4 Response Handler] Request failed for destination ${dest} with status: ${status}`, + status, + { + [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(status), + }, + destinationResponse, + ); + } + + return { + status, + message, + destinationResponse, + }; +}; + +function networkHandler() { + this.responseHandler = responseHandler; + this.proxy = proxyRequest; + this.prepareProxy = prepareProxyRequest; + this.processAxiosResponse = processAxiosResponse; +} + +module.exports = { + networkHandler, +}; From ba3c162e2e2314feae548d021694fc9d5cf6c306 Mon Sep 17 00:00:00 2001 From: Yashasvi Bajpai <33063622+yashasvibajpai@users.noreply.github.com> Date: Thu, 30 Nov 2023 13:33:35 +0530 Subject: [PATCH 2/7] chore: add network handler --- src/features.json | 1 - .../adobe_analytics/networkHandler.js | 65 +++++++------------ 2 files changed, 24 insertions(+), 42 deletions(-) diff --git a/src/features.json b/src/features.json index 848b606b47..224968c99b 100644 --- a/src/features.json +++ b/src/features.json @@ -1,7 +1,6 @@ { "routerTransform": { "ACTIVE_CAMPAIGN": true, - "ADOBE_ANALYTICS": true, "ALGOLIA": true, "CANDU": true, "DELIGHTED": true, diff --git a/src/v0/destinations/adobe_analytics/networkHandler.js b/src/v0/destinations/adobe_analytics/networkHandler.js index 4b8de886e3..b5b58ade0c 100644 --- a/src/v0/destinations/adobe_analytics/networkHandler.js +++ b/src/v0/destinations/adobe_analytics/networkHandler.js @@ -1,57 +1,40 @@ -const { NetworkError } = require('@rudderstack/integrations-lib'); +const { InstrumentationError } = require('@rudderstack/integrations-lib'); const { proxyRequest, prepareProxyRequest } = require('../../../adapters/network'); const { - getDynamicErrorType, processAxiosResponse, } = require('../../../adapters/utils/networkUtils'); const { DESTINATION } = require('./config'); -const { isDefinedAndNotNull, isDefined, isHttpStatusSuccess } = require('../../util'); -const tags = require('../../util/tags'); + +/** + * Extract data inside different tags from an xml payload + * @param {*} xml + * @param {*} tagName + * @returns data inside the tagName + */ +function extractContent(xmlPayload, tagName) { + const pattern = new RegExp(`<${tagName}>(.*?)`); + const match = xmlPayload.match(pattern); + return match ? match[1] : null; +} const responseHandler = (destinationResponse, dest) => { const message = `[${DESTINATION}] - Request Processed Successfully`; - let { status, reason } = destinationResponse; - const { response } = destinationResponse; - if (status === 204) { - // GA4 always returns a 204 response, other than in case of - // validation endpoint. - status = 200; - } else if ( - status === 200 && - isDefinedAndNotNull(response) && - isDefined(response.validationMessages) - ) { - // for GA4 debug validation endpoint, status is always 200 - // validationMessages[] is empty, thus event is valid - if (response.validationMessages?.length === 0) { - status = 200; + const { response, status } = destinationResponse; + + // Extract values between different tags + const responseStatus = extractContent(response, 'status'); + const reason = extractContent(response, 'reason'); + + // if the status tag in XML contains FAILURE, we build and throw an explicit error + if (responseStatus === 'FAILURE') { + if (reason) { + throw new InstrumentationError(`[${DESTINATION} Response Handler] Request failed for destination ${dest} : ${reason}` ) } else { - // Build the error in case the validationMessages[] is non-empty - const { description, validationCode, fieldPath } = response.validationMessages[0]; - throw new NetworkError( - `Validation Server Response Handler:: Validation Error for ${dest} of field path :${fieldPath} | ${validationCode}-${description}`, - status, - { - [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(status), - }, - response?.validationMessages[0]?.description, - ); + throw new InstrumentationError(`[${DESTINATION} Response Handler] Request failed for destination ${dest} with a general error`) } } - // if the response from destination is not a success case build an explicit error - if (!isHttpStatusSuccess(status)) { - throw new NetworkError( - `[GA4 Response Handler] Request failed for destination ${dest} with status: ${status}`, - status, - { - [tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(status), - }, - destinationResponse, - ); - } - return { status, message, From a245f1817897f36b980f4033348eef41ed6ccfc8 Mon Sep 17 00:00:00 2001 From: Yashasvi Bajpai <33063622+yashasvibajpai@users.noreply.github.com> Date: Tue, 5 Dec 2023 01:51:26 +0530 Subject: [PATCH 3/7] chore: add test --- .../adobe_analytics/dataDelivery/data.ts | 53 +++++++++++++++++++ .../destinations/adobe_analytics/network.ts | 17 ++++++ 2 files changed, 70 insertions(+) create mode 100644 test/integrations/destinations/adobe_analytics/dataDelivery/data.ts create mode 100644 test/integrations/destinations/adobe_analytics/network.ts diff --git a/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts b/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts new file mode 100644 index 0000000000..8f5442fb6f --- /dev/null +++ b/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts @@ -0,0 +1,53 @@ +export const data = [ + { + name: 'adobe_analytics', + description: 'Test 0', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://adobe.failure.omtrdc.net/b/ss//6', + headers: { + 'Content-type': 'application/xml', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: { + payload: + '17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerprodViewGames;;11;148.39rudderstackfootlockerpoc', + }, + FORM: {}, + }, + files: {}, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 500, + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'ADOBE_ANALYTICS', + module: 'destination', + implementation: 'native', + feature: 'dataDelivery', + destinationId: '2S3s0dFD0DqL7m0UkfBwyblDrzs', + workspaceId: '1pKWrE6GwAvFwKBikka1SbRgrSN', + }, + destinationResponse: '', + authErrorCategory: '', + message: + '[ADOBE_ANALYTICS Response Handler] Request failed for destination adobe_analytics : NO pagename OR pageurl', + }, + }, + }, +]; diff --git a/test/integrations/destinations/adobe_analytics/network.ts b/test/integrations/destinations/adobe_analytics/network.ts new file mode 100644 index 0000000000..35fe44804c --- /dev/null +++ b/test/integrations/destinations/adobe_analytics/network.ts @@ -0,0 +1,17 @@ +export const networkCallsData = [ + { + httpReq: { + url: 'https://adobe.failure.omtrdc.net/b/ss//6', + params: {}, + headers: { + 'Content-type': 'application/xml', + }, + method: 'POST', + }, + httpRes: { + status: 400, + message: + '[ADOBE_ANALYTICS Response Handler] Request failed for destination adobe_analytics : NO pagename OR pageurl', + }, + }, +]; From 5b403cacdbfe5baf381704f196d4b03f3deccfa1 Mon Sep 17 00:00:00 2001 From: Sai Sankeerth Date: Mon, 11 Dec 2023 14:23:51 +0530 Subject: [PATCH 4/7] fix: adding correct mock with corrections & modify the status-code in test-case Signed-off-by: Sai Sankeerth --- .../destinations/adobe_analytics/dataDelivery/data.ts | 2 +- test/integrations/destinations/adobe_analytics/network.ts | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts b/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts index 8f5442fb6f..b3aa1e7860 100644 --- a/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts +++ b/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts @@ -32,7 +32,7 @@ export const data = [ }, output: { response: { - status: 500, + status: 400, statTags: { errorCategory: 'dataValidation', errorType: 'instrumentation', diff --git a/test/integrations/destinations/adobe_analytics/network.ts b/test/integrations/destinations/adobe_analytics/network.ts index 35fe44804c..c6d83e9813 100644 --- a/test/integrations/destinations/adobe_analytics/network.ts +++ b/test/integrations/destinations/adobe_analytics/network.ts @@ -2,16 +2,16 @@ export const networkCallsData = [ { httpReq: { url: 'https://adobe.failure.omtrdc.net/b/ss//6', + data: '17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerprodViewGames;;11;148.39rudderstackfootlockerpoc', params: {}, headers: { - 'Content-type': 'application/xml', + 'Content-Type': 'application/xml', }, method: 'POST', }, httpRes: { - status: 400, - message: - '[ADOBE_ANALYTICS Response Handler] Request failed for destination adobe_analytics : NO pagename OR pageurl', + status: 200, + data: 'FAILURENO pagename OR pageurl', }, }, ]; From 554a5a159d80fba83f829bff997095fea7820857 Mon Sep 17 00:00:00 2001 From: Yashasvi Bajpai <33063622+yashasvibajpai@users.noreply.github.com> Date: Mon, 11 Dec 2023 14:54:16 +0530 Subject: [PATCH 5/7] chore: add dummy destination id --- .../destinations/adobe_analytics/dataDelivery/data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts b/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts index b3aa1e7860..e96f4ba81d 100644 --- a/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts +++ b/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts @@ -40,7 +40,7 @@ export const data = [ module: 'destination', implementation: 'native', feature: 'dataDelivery', - destinationId: '2S3s0dFD0DqL7m0UkfBwyblDrzs', + destinationId: '2S3s0dXXXXXX7m0UfBwyblDrzs', workspaceId: '1pKWrE6GwAvFwKBikka1SbRgrSN', }, destinationResponse: '', From 22db262474cca8f29ba6e008377262a9b77ca045 Mon Sep 17 00:00:00 2001 From: Yashasvi Bajpai <33063622+yashasvibajpai@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:10:53 +0530 Subject: [PATCH 6/7] chore: add dummy ws id --- .../destinations/adobe_analytics/dataDelivery/data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts b/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts index e96f4ba81d..f63b6ab0e1 100644 --- a/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts +++ b/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts @@ -41,7 +41,7 @@ export const data = [ implementation: 'native', feature: 'dataDelivery', destinationId: '2S3s0dXXXXXX7m0UfBwyblDrzs', - workspaceId: '1pKWrE6GwAvFwKBikka1SbRgrSN', + workspaceId: '1pKWrE6GXXXXXKBikka1SbRgrSN', }, destinationResponse: '', authErrorCategory: '', From ecc73221c68ac9597561a33647b8f3d19c449038 Mon Sep 17 00:00:00 2001 From: Yashasvi Bajpai <33063622+yashasvibajpai@users.noreply.github.com> Date: Mon, 11 Dec 2023 15:52:27 +0530 Subject: [PATCH 7/7] chore: add tests for success and generic error case --- .../adobe_analytics/dataDelivery/data.ts | 93 ++++++++++++++++++- .../destinations/adobe_analytics/network.ts | 32 ++++++- 2 files changed, 122 insertions(+), 3 deletions(-) diff --git a/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts b/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts index f63b6ab0e1..182969da73 100644 --- a/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts +++ b/test/integrations/destinations/adobe_analytics/dataDelivery/data.ts @@ -1,7 +1,7 @@ export const data = [ { name: 'adobe_analytics', - description: 'Test 0', + description: 'Test 0: Failure response from Adobe Analytics with reason', feature: 'dataDelivery', module: 'destination', version: 'v0', @@ -21,7 +21,7 @@ export const data = [ JSON_ARRAY: {}, XML: { payload: - '17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerprodViewGames;;11;148.39rudderstackfootlockerpoc', + '17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerprodViewGames;;11;148.39failureReport', }, FORM: {}, }, @@ -50,4 +50,93 @@ export const data = [ }, }, }, + { + name: 'adobe_analytics', + description: 'Test 1: Failure response from Adobe Analytics without reason (Generic error)', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://adobe.failure2.omtrdc.net/b/ss//6', + headers: { + 'Content-type': 'application/xml', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: { + payload: + '17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerprodViewGames;;11;148.39failureReportgeneric', + }, + FORM: {}, + }, + files: {}, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 400, + statTags: { + errorCategory: 'dataValidation', + errorType: 'instrumentation', + destType: 'ADOBE_ANALYTICS', + module: 'destination', + implementation: 'native', + feature: 'dataDelivery', + destinationId: '2S3s0dXXXXXX7m0UfBwyblDrzs', + workspaceId: '1pKWrE6GXXXXXKBikka1SbRgrSN', + }, + destinationResponse: '', + authErrorCategory: '', + message: + '[ADOBE_ANALYTICS Response Handler] Request failed for destination adobe_analytics with a general error', + }, + }, + }, + { + name: 'adobe_analytics', + description: 'Test 2: Success response from Adobe Analytics', + feature: 'dataDelivery', + module: 'destination', + version: 'v0', + input: { + request: { + body: { + version: '1', + type: 'REST', + method: 'POST', + endpoint: 'https://adobe.success.omtrdc.net/b/ss//6', + headers: { + 'Content-type': 'application/xml', + }, + params: {}, + body: { + JSON: {}, + JSON_ARRAY: {}, + XML: { + payload: + '127.0.1.0www.google.co.inGoogleid1110011prodViewGames;Monopoly;1;14.00,Games;UNO;2;6.90successreport', + }, + FORM: {}, + }, + files: {}, + }, + method: 'POST', + }, + }, + output: { + response: { + status: 200, + destinationResponse: 'SUCCESS', + }, + }, + }, ]; diff --git a/test/integrations/destinations/adobe_analytics/network.ts b/test/integrations/destinations/adobe_analytics/network.ts index c6d83e9813..2fe4f0204e 100644 --- a/test/integrations/destinations/adobe_analytics/network.ts +++ b/test/integrations/destinations/adobe_analytics/network.ts @@ -2,7 +2,7 @@ export const networkCallsData = [ { httpReq: { url: 'https://adobe.failure.omtrdc.net/b/ss//6', - data: '17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerprodViewGames;;11;148.39rudderstackfootlockerpoc', + data: '17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerprodViewGames;;11;148.39failureReport', params: {}, headers: { 'Content-Type': 'application/xml', @@ -14,4 +14,34 @@ export const networkCallsData = [ data: 'FAILURENO pagename OR pageurl', }, }, + { + httpReq: { + url: 'https://adobe.failure2.omtrdc.net/b/ss//6', + data: '17941080sales campaignwebUSD127.0.0.1en-USDalvik/2.1.0 (Linux; U; Android 9; Android SDK built for x86 Build/PSR1.180720.075)https://www.google.com/search?q=estore+bestsellerprodViewGames;;11;148.39failureReportgeneric', + params: {}, + headers: { + 'Content-Type': 'application/xml', + }, + method: 'POST', + }, + httpRes: { + status: 200, + data: 'FAILURE', + }, + }, + { + httpReq: { + url: 'https://adobe.success.omtrdc.net/b/ss//6', + data: '127.0.1.0www.google.co.inGoogleid1110011prodViewGames;Monopoly;1;14.00,Games;UNO;2;6.90successreport', + params: {}, + headers: { + 'Content-Type': 'application/xml', + }, + method: 'POST', + }, + httpRes: { + status: 200, + data: 'SUCCESS', + }, + }, ];