Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: refactor new error types ( amplitude, algolia, appcues, attentive_tag, attribution, autopilot) #1648

Merged
merged 9 commits into from
Dec 14, 2022
15 changes: 3 additions & 12 deletions src/cdk/autopilot/transform.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const { Utils } = require("rudder-transformer-cdk");
const ErrorBuilder = require("../../v0/util/error");
const { TRANSFORMER_METRIC } = require("../../v0/util/constant");
const { InstrumentationError } = require("../../v0/util/errorTypes");

function identifyPostMapper(event, mappedPayload, rudderContext) {
const { message } = event;
Expand Down Expand Up @@ -51,16 +50,8 @@ function trackPostMapper(event, mappedPayload, rudderContext) {
* - if no stat is being set from here, CDK will treat it as an unexpected error occuring in PostMapper
* and it shall be treated with priority P0
*/
throw new ErrorBuilder()
.setStatus(400)
.setMessage("Email is required for track calls")
.setStatTags({
destination: "autopilot",
stage: TRANSFORMER_METRIC.TRANSFORMER_STAGE.TRANSFORM,
scope: TRANSFORMER_METRIC.MEASUREMENT_TYPE.TRANSFORMATION.SCOPE,
meta: TRANSFORMER_METRIC.MEASUREMENT_TYPE.TRANSFORMATION.META.BAD_PARAM
})
.build();
throw new InstrumentationError("Email is required for track calls");

// throw new Error("Email is required for track calls");
}
// The plan is to delete the rudderResponse property from the mappedPayload finally
Expand Down
26 changes: 15 additions & 11 deletions src/v0/destinations/algolia/transform.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
const set = require("set-value");
const { EventType } = require("../../../constants");
const {
InstrumentationError,
ConfigurationError
} = require("../../util/errorTypes");
const {
getValueFromMessage,
constructPayload,
Expand All @@ -24,7 +28,7 @@ const {
const trackResponseBuilder = (message, { Config }) => {
let event = getValueFromMessage(message, "event");
if (!event) {
throw new TransformationError("event is required for track call");
throw new InstrumentationError("event is required for track call");
}
event = event.trim().toLowerCase();
let payload = constructPayload(message, trackMapping);
Expand All @@ -34,7 +38,7 @@ const trackResponseBuilder = (message, { Config }) => {
getValueFromMessage(message, "properties.eventType") || eventMapping[event];

if (!payload.eventType) {
throw new TransformationError("eventType is mandatory for track call");
throw new InstrumentationError("eventType is mandatory for track call");
}
payload = genericpayloadValidator(payload);

Expand All @@ -57,19 +61,19 @@ const trackResponseBuilder = (message, { Config }) => {
}
// making size of object list and position list equal
if (posLen > 0 && objLen > 0 && posLen !== objLen) {
throw new TransformationError(
throw new InstrumentationError(
"length of objectId and position should be equal"
);
}
}
}
// for all events either filter or objectID should be there
if (!payload.filters && !payload.objectIDs) {
throw new TransformationError("Either filters or objectIds is required.");
throw new InstrumentationError("Either filters or objectIds is required.");
}
if (payload.filters && payload.objectIDs) {
throw new TransformationError(
"event can't have both objectIds and filters at the same time."
throw new InstrumentationError(
"event cant have both objectIds and filters at the same time."
);
}
if (payload.eventType === "click") {
Expand All @@ -89,16 +93,16 @@ const trackResponseBuilder = (message, { Config }) => {
const process = event => {
const { message, destination } = event;
if (!message.type) {
throw new TransformationError(
throw new InstrumentationError(
"message Type is not present. Aborting message."
);
}

if (!destination.Config.apiKey) {
throw new TransformationError("Invalid Api Key");
throw new ConfigurationError("Invalid Api Key");
}
if (!destination.Config.applicationId) {
throw new TransformationError("Invalid Application Id");
throw new ConfigurationError("Invalid Application Id");
}
const messageType = message.type.toLowerCase();

Expand All @@ -108,7 +112,7 @@ const process = event => {
response = trackResponseBuilder(message, destination);
break;
default:
throw new TransformationError(
throw new InstrumentationError(
`message type ${messageType} not supported`
);
}
Expand All @@ -117,7 +121,7 @@ const process = event => {

const processRouterDest = async inputs => {
if (!Array.isArray(inputs) || inputs.length === 0) {
throw new TransformationError("Invalid event array");
throw new InstrumentationError("Invalid event array");
}

const inputChunks = returnArrayOfSubarrays(inputs, MAX_BATCH_SIZE);
Expand Down
11 changes: 5 additions & 6 deletions src/v0/destinations/algolia/util.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const logger = require("../../../logger");
const { TransformationError } = require("../../util");
const { InstrumentationError } = require("../../util/errorTypes");
const { EVENT_TYPES } = require("./config");

/**
Expand Down Expand Up @@ -28,7 +28,7 @@ const genericpayloadValidator = payload => {
const updatedPayload = payload;
updatedPayload.eventType = payload.eventType.trim().toLowerCase();
if (!EVENT_TYPES.includes(payload.eventType)) {
throw new TransformationError(
throw new InstrumentationError(
"eventType can be either click, view or conversion"
);
}
Expand Down Expand Up @@ -115,7 +115,7 @@ const clickPayloadValidator = payload => {
}
if (payload.objectIDs && payload.positions) {
if (payload.objectIDs.length !== payload.positions.length) {
throw new TransformationError(
throw new InstrumentationError(
"length of objectId and position should be equal"
);
}
Expand All @@ -125,9 +125,8 @@ const clickPayloadValidator = payload => {
(payload.positions && !payload.queryID) ||
(!payload.positions && payload.queryID)
) {
throw new TransformationError(
"for click eventType either both positions and queryId should be present or none",
400
throw new InstrumentationError(
"for click eventType either both positions and queryId should be present or none"
);
}
}
Expand Down
34 changes: 24 additions & 10 deletions src/v0/destinations/am/deleteUsers.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
const btoa = require("btoa");
const { httpSend } = require("../../../adapters/network");
const { CustomError } = require("../../util");
const { getDynamicErrorType } = require("../../../adapters/utils/networkUtils");

const {
NetworkError,
RetryableError,
InstrumentationError,
ConfigurationError
} = require("../../util/errorTypes");
const { executeCommonValidations } = require("../../util/regulation-api");
const tags = require("../../util/tags");

const userDeletionHandler = async (userAttributes, config) => {
if (!config) {
throw new CustomError("Config for deletion not present", 400);
throw new ConfigurationError("Config for deletion not present");
}
const { apiKey, apiSecret } = config;
if (!apiKey || !apiSecret) {
throw new CustomError("api key/secret for deletion not present", 400);
throw new ConfigurationError("api key/secret for deletion not present");
}

for (let i = 0; i < userAttributes.length; i += 1) {
const uId = userAttributes[i].userId;
if (!uId) {
throw new CustomError("User id for deletion not present", 400);
throw new InstrumentationError("User id for deletion not present");
}
const data = { user_ids: [uId], requester: "RudderStack" };
const requestOptions = {
Expand All @@ -29,17 +37,23 @@ const userDeletionHandler = async (userAttributes, config) => {
};
const resp = await httpSend(requestOptions);
if (!resp || !resp.response) {
throw new CustomError("Could not get response", 500);
throw new RetryableError("Could not get response");
}
if (
resp &&
resp.response &&
resp.response.response &&
resp.response.response.status !== 200 // am sends 400 for any bad request or even if user id is not found. The text is also "Bad Request" so not handling user not found case
resp.response?.response &&
resp.response?.response?.status !== 200 // am sends 400 for any bad request or even if user id is not found. The text is also "Bad Request" so not handling user not found case
) {
throw new CustomError(
resp.response.response.statusText || "Error while deleting user",
resp.response.response.status
throw new NetworkError(
resp.response?.response?.statusText || "Error while deleting user",
resp.response?.response?.status,
{
[tags.TAG_NAMES.ERROR_TYPE]: getDynamicErrorType(
resp.response?.response?.status
)
},
resp
);
}
}
Expand Down
40 changes: 4 additions & 36 deletions src/v0/destinations/am/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ const {
isAppleFamily,
isDefinedAndNotNullAndNotEmpty
} = require("../../util");
const ErrorBuilder = require("../../util/error");
const {
DESTINATION,
BASE_URL,
BASE_URL_EU,
ConfigCategory,
Expand All @@ -42,6 +40,7 @@ const {
const AMUtils = require("./utils");

const logger = require("../../../logger");
const { InstrumentationError } = require("../../util/errorTypes");

const AMBatchSizeLimit = 20 * 1024 * 1024; // 20 MB
const AMBatchEventLimit = 500; // event size limit from sdk is 32KB => 15MB
Expand Down Expand Up @@ -610,18 +609,7 @@ function processSingleMessage(message, destination) {
groupInfo.group_properties = groupTraits;
} else {
logger.debug("Group call parameters are not valid");
throw new ErrorBuilder()
.setStatus(400)
.setMessage("Group call parameters are not valid")
.setStatTags({
destType: DESTINATION,
stage: TRANSFORMER_METRIC.TRANSFORMER_STAGE.TRANSFORM,
scope: TRANSFORMER_METRIC.MEASUREMENT_TYPE.TRANSFORMATION.SCOPE,
meta:
TRANSFORMER_METRIC.MEASUREMENT_TYPE.TRANSFORMATION.META
.INSTRUMENTATION
})
.build();
throw new InstrumentationError("Group call parameters are not valid");
}
}
break;
Expand All @@ -635,17 +623,7 @@ function processSingleMessage(message, destination) {
case EventType.TRACK:
evType = message.event;
if (!isDefinedAndNotNullAndNotEmpty(evType)) {
throw new ErrorBuilder()
.setStatus(400)
.setMessage("message type not defined")
.setStatTags({
destType: DESTINATION,
stage: TRANSFORMER_METRIC.TRANSFORMER_STAGE.TRANSFORM,
scope: TRANSFORMER_METRIC.MEASUREMENT_TYPE.TRANSFORMATION.SCOPE,
meta:
TRANSFORMER_METRIC.MEASUREMENT_TYPE.TRANSFORMATION.META.BAD_EVENT
})
.build();
throw new InstrumentationError("message type not defined");
}
if (
message.properties &&
Expand All @@ -661,17 +639,7 @@ function processSingleMessage(message, destination) {
break;
default:
logger.debug("could not determine type");
throw new ErrorBuilder()
.setStatus(400)
.setMessage("message type not supported")
.setStatTags({
destType: DESTINATION,
stage: TRANSFORMER_METRIC.TRANSFORMER_STAGE.TRANSFORM,
scope: TRANSFORMER_METRIC.MEASUREMENT_TYPE.TRANSFORMATION.SCOPE,
meta:
TRANSFORMER_METRIC.MEASUREMENT_TYPE.TRANSFORMATION.META.BAD_EVENT
})
.build();
throw new InstrumentationError("message type not supported");
}
return responseBuilderSimple(
groupInfo,
Expand Down
19 changes: 10 additions & 9 deletions src/v0/destinations/appcues/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ const {
removeUndefinedAndNullAndEmptyValues,
getSuccessRespEvents,
getErrorRespEvents,
CustomError
generateErrorObject
} = require("../../util");
const { InstrumentationError } = require("../../util/errorTypes");

const { ConfigCategory, mappingConfig, getEndpoint } = require("./config");

Expand Down Expand Up @@ -70,16 +71,14 @@ function process(event) {
const { message, destination } = event;

if (!message.type) {
throw new CustomError(
"Message Type is not present. Aborting message.",
400
throw new InstrumentationError(
"Message Type is not present. Aborting message."
);
}

if (!message.userId) {
throw new CustomError(
"User id is absent. Aborting event as userId is mandatory for Appcues",
400
throw new InstrumentationError(
"User id is absent. Aborting event as userId is mandatory for Appcues"
);
}

Expand Down Expand Up @@ -113,7 +112,7 @@ function process(event) {
getEndpoint(destination.Config.accountId, message.userId)
);
default:
throw new CustomError("Message type is not supported", 400);
throw new InstrumentationError("Message type is not supported");
}
}

Expand Down Expand Up @@ -141,14 +140,16 @@ const processRouterDest = async inputs => {
input.destination
);
} catch (error) {
const errRes = generateErrorObject(error);
return getErrorRespEvents(
[input.metadata],
error.response
? error.response.status
: error.code
? error.code
: 400,
error.message || "Error occurred while processing payload."
error.message || "Error occurred while processing payload.",
errRes.statTags
);
}
})
Expand Down
Loading