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

Better logs V2 #2376

Merged
merged 22 commits into from
Jul 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ccad0b0
add org to ngp van error log message
engelhartrueben Jun 7, 2024
2ad40ae
call each configuration variable individually so we can check which f…
engelhartrueben Jun 7, 2024
2d6695d
add org name to error when retrieving a saved list from VAN fails
engelhartrueben Jun 10, 2024
d7c4f37
clean up message review query to make more readable on the backend
engelhartrueben Jun 10, 2024
a559cc1
clean up getConversations contact id to make more readable on the bac…
engelhartrueben Jun 10, 2024
fdb5011
add boolean interpertation to awsContext + no filter context
engelhartrueben Jun 10, 2024
1d0df78
clean query 2, making more readable on backend
engelhartrueben Jun 10, 2024
e188231
add cardinality to getConversations queries
engelhartrueben Jun 10, 2024
a7498ae
clean up query three in getConversations
engelhartrueben Jun 10, 2024
a9ae018
seperate out each component of result
engelhartrueben Jun 10, 2024
9c259f5
add clarity to NPG VAN error
engelhartrueben Jun 13, 2024
522c722
clean auto-opt log. removed logging the regex as that seemed unnecess…
engelhartrueben Jun 26, 2024
4663501
add comments to what opt-out function does
engelhartrueben Jun 26, 2024
fe392d5
add comment to clarify what the default base64 regex opt-out is
engelhartrueben Jun 26, 2024
9103abe
add context to postMessageSave optout reason log
engelhartrueben Jun 26, 2024
f96762a
remove log for testing (jr. dev sillyness, lets be real)
engelhartrueben Jun 26, 2024
e675bac
clarify and reduce Contact Reply log.
engelhartrueben Jun 26, 2024
a235750
Fix test when there is an error retrieving a list from VAN. Creates o…
engelhartrueben Jun 26, 2024
1cfbc18
add organzation to ngp van tests for use in several functions that ca…
engelhartrueben Jun 26, 2024
19ea9f9
remove the silly jr devs HERE log
engelhartrueben Jul 3, 2024
18ade2a
its me, the jr dev. removing yet another HERE log
engelhartrueben Jul 3, 2024
0a1eeaa
Merge branch 'stage-main-14.1' into better-logs-2
engelhartrueben Jul 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions __test__/extensions/contact-loaders/ngpvan/ngpvan.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ describe("ngpvan", () => {
let oldNgpVanWebhookUrl;
let oldNgpVanAppName;
let oldNgpVanApiKey;
let organization;

beforeEach(async () => {
oldNgpVanWebhookUrl = process.env.NGP_VAN_WEBHOOK_BASE_URL;
Expand All @@ -51,6 +52,7 @@ describe("ngpvan", () => {
process.env.NGP_VAN_WEBHOOK_BASE_URL = "https://www.example.com";
process.env.NGP_VAN_APP_NAME = "spoke";
process.env.NGP_VAN_API_KEY = "topsecret";
organization = { name: "TESTING" }
});

afterEach(async () => {
Expand All @@ -61,7 +63,7 @@ describe("ngpvan", () => {
});

it("returns true when all required environment variables are present", async () => {
expect(await available()).toEqual({
expect(await available(organization)).toEqual({
result: true,
expiresSeconds: 86400
});
Expand All @@ -73,7 +75,7 @@ describe("ngpvan", () => {
});

it("returns false", async () => {
expect(await available()).toEqual({
expect(await available(organization)).toEqual({
result: false,
expiresSeconds: 86400
});
Expand All @@ -88,6 +90,7 @@ describe("ngpvan", () => {
let oldNgpVanCacheTtl;
let oldNgpVanApiBaseUrl;
let listItems;
let organization;

beforeEach(async () => {
oldMaximumListSize = process.env.NGP_VAN_MAXIMUM_LIST_SIZE;
Expand All @@ -100,6 +103,7 @@ describe("ngpvan", () => {
process.env.NGP_VAN_API_KEY = "topsecret";
process.env.NGP_VAN_CACHE_TTL = 30;
process.env.NGP_VAN_API_BASE_URL = fakeNgpVanBaseApiUrl;
organization = {name: "TESTING"};
});

beforeEach(async () => {
Expand Down Expand Up @@ -222,11 +226,10 @@ describe("ngpvan", () => {
)
.reply(404);

const savedListsResponse = await getClientChoiceData();

const savedListsResponse = await getClientChoiceData(organization);
expect(JSON.parse(savedListsResponse.data)).toEqual({
error: expect.stringMatching(
/Error retrieving saved list metadata from VAN Error: Request id .+ failed; received status 404/
/TESTING :: Error retrieving saved list metadata from VAN Error: Request id .+ failed; received status 404/
)
});
getSavedListsNock.done();
Expand Down
17 changes: 12 additions & 5 deletions src/extensions/action-handlers/ngpvan-action.js
Original file line number Diff line number Diff line change
Expand Up @@ -370,15 +370,22 @@ export async function getClientChoiceData(organization) {
// Besides this returning true, "test-action" will also need to be added to
// process.env.ACTION_HANDLERS
export async function available(organization) {
let result =
(hasConfig("NGP_VAN_API_KEY", organization) ||
hasConfig("NGP_VAN_API_KEY_ENCRYPTED", organization)) &&
hasConfig("NGP_VAN_APP_NAME", organization);
const hasVanApiKey = hasConfig("NGP_VAN_API_KEY", organization);
const hasVanApiKeyEncrypted = hasConfig("NGP_VAN_API_KEY_ENCRYPTED", organization);
const hasVanAppName = hasConfig("NGP_VAN_APP_NAME", organization);

let result = (hasVanApiKey || hasVanApiKeyEncrypted) && hasVanAppName;

if (!result) {
// eslint-disable-next-line no-console
console.info(
"ngpvan-action unavailable. Missing one or more required environment variables"
`${organization.name} :: ngpvan-action unavailable. Status:
Needs either:\n
\tNGP_VAN_API_KEY: ${hasVanApiKey}\n
\tNGP_VAN_API_KEY_ENCRYPTED: ${hasVanApiKeyEncrypted}\n
Needs:\n
\tNGP_VAN_APP_NAME: ${hasVanAppName}
`
);
}

Expand Down
21 changes: 14 additions & 7 deletions src/extensions/contact-loaders/ngpvan/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,23 @@ export async function available(organization, user) {
// / If this is instantaneous, you can have it be 0 (i.e. always), but if it takes time
// / to e.g. verify credentials or test server availability,
// / then it's better to allow the result to be cached

const hasRawKey = hasConfig("NGP_VAN_API_KEY", organization);
const hasEncryptedKey = hasConfig("NGP_VAN_API_KEY_ENCRYPTED", organization)
const hasAppName = hasConfig("NGP_VAN_APP_NAME", organization);
const hasWebhook = hasConfig("NGP_VAN_WEBHOOK_BASE_URL", organization)

const result =
(hasConfig("NGP_VAN_API_KEY", organization) ||
hasConfig("NGP_VAN_API_KEY_ENCRYPTED", organization)) &&
hasConfig("NGP_VAN_APP_NAME", organization) &&
hasConfig("NGP_VAN_WEBHOOK_BASE_URL", organization);
const result = (hasRawKey || hasEncryptedKey) && hasAppName && hasWebhook;

if (!result) {
console.log(
"ngpvan contact loader unavailable. Missing one or more required environment variables."
`${organization.name} :: ngpvan contact loader unavailable. Status:\n
Needs one:\n
\tNGP_VAN_API_KEY: ${hasRawKey}\n
\tNGP_VAN_API_KEY_ENCRYPTED: ${hasEncryptedKey}\n
Needs both:\n
\tNGP_VAN_APP_NAME: ${hasAppName}\n
\tNGP_VAN_WEBHOOK_BASE_URL: ${hasWebhook}`
);
}

Expand Down Expand Up @@ -145,7 +152,7 @@ export async function getClientChoiceData(organization, campaign, user) {
}
}
} catch (error) {
const message = `Error retrieving saved list metadata from VAN ${error}`;
const message = `${organization.name} :: Error retrieving saved list metadata from VAN ${error}`;
// eslint-disable-next-line no-console
console.log(message);
return { data: `${JSON.stringify({ error: message })}` };
Expand Down
32 changes: 21 additions & 11 deletions src/extensions/message-handlers/auto-optout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ import { sendRawMessage } from "../../../server/api/mutations/sendMessage";
const DEFAULT_AUTO_OPTOUT_REGEX_LIST_BASE64 =
"W3sicmVnZXgiOiAiXlxccypzdG9wXFxifFxcYnJlbW92ZSBtZVxccyokfHJlbW92ZSBteSBuYW1lfFxcYnRha2UgbWUgb2ZmIHRoXFx3KyBsaXN0fFxcYmxvc2UgbXkgbnVtYmVyfGRvblxcVz90IGNvbnRhY3QgbWV8ZGVsZXRlIG15IG51bWJlcnxJIG9wdCBvdXR8c3RvcDJxdWl0fHN0b3BhbGx8Xlxccyp1bnN1YnNjcmliZVxccyokfF5cXHMqY2FuY2VsXFxzKiR8XlxccyplbmRcXHMqJHxeXFxzKnF1aXRcXHMqJCIsICJyZWFzb24iOiAic3RvcCJ9XQ==";

// DEFAULT_AUTO_OPTOUT_REGEX_LIST_BASE64 converts to:

// [{"regex": "^\\s*stop\\b|\\bremove me\\s*$|remove my name|\\btake me off th\\w+ list|
// \\blose my number|don\\W?t contact me|delete my number|I opt out|stop2quit|stopall|
// ^\\s*unsubscribe\\s*$|^\\s*cancel\\s*$|^\\s*end\\s*$|^\\s*quit\\s*$",
// "reason": "stop"}]

export const serverAdministratorInstructions = () => {
return {
description: `
Expand Down Expand Up @@ -43,26 +50,29 @@ export const available = organization => {
}
};

// Part of the auto-opt out process.
// checks if message recieved states something like "stop", "quit", or "stop2quit"
export const preMessageSave = async ({ messageToSave, organization }) => {
if (messageToSave.is_from_contact) {
if (messageToSave.is_from_contact) { // checks if message is from the contact
const config = Buffer.from(
getConfig("AUTO_OPTOUT_REGEX_LIST_BASE64", organization) ||
DEFAULT_AUTO_OPTOUT_REGEX_LIST_BASE64,
"base64"
).toString();
).toString(); // converts DEFAULT_AUTO_OPTOUT_REGEX_LIST_BASE64 to regex
// can be custom set in .env w/ AUTO_OPTOUT_REGEX_LIST_BASE64
const regexList = JSON.parse(config || "[]");
const matches = regexList.filter(matcher => {
const matches = regexList.filter(matcher => { // checks if message contains opt-out langauge
const re = new RegExp(matcher.regex, "i");
return String(messageToSave.text).match(re);
});
// console.log("auto-optout", matches, messageToSave.text, regexList);
if (matches.length) {
if (matches.length) { // if more than one match, opt-out
console.log(
"auto-optout MATCH",
messageToSave.campaign_contact_id,
matches
`| campaign_contact_id: ${messageToSave.campaign_contact_id}`,
`| reason: "${matches[0].reason}"`
);
const reason = matches[0].reason || "auto_optout";
const reason = matches[0].reason || "auto_optout"; // with default opt-out regex,
// reason will always be "stop"
messageToSave.error_code = -133;
return {
contactUpdates: {
Expand All @@ -89,8 +99,8 @@ export const postMessageSave = async ({
if (message.is_from_contact && handlerContext.autoOptOutReason) {
console.log(
"auto-optout.postMessageSave",
message.campaign_contact_id,
handlerContext.autoOptOutReason
`| campaign_contact_id: ${message.campaign_contact_id}`,
`| opt-out reason: ${handlerContext.autoOptOutReason}`
);
let contact = await cacheableData.campaignContact.load(
message.campaign_contact_id,
Expand Down Expand Up @@ -153,4 +163,4 @@ export const postMessageSave = async ({
});
}
}
};
};
16 changes: 15 additions & 1 deletion src/extensions/service-vendors/twilio/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,21 @@ export async function handleIncomingMessage(message) {
const finalMessage = await convertMessagePartsToMessage([
pendingMessagePart
]);
console.log("Contact reply", finalMessage, pendingMessagePart);
console.log(
"Contact Reply\n",
`\t| Message Status: ${finalMessage.send_status}\n`,
`\t| From Contact? : ${finalMessage.is_from_contact}\n`,
`\t| Contact Number: ${finalMessage.contact_number}\n`,
`\t| User Number: ${finalMessage.user_number}\n`,
`\t| Text: ${finalMessage.text.replace(/(\r\n|\n|\r)/gm, " ").substring(0, 45)}\n`,
`\t| Error Code: ${finalMessage.error_code}\n`,
`\t| Service: ${finalMessage.service || pendingMessagePart.service}\n`,
`\t| Media: ${finalMessage.media.length === 0 ? "No media" : finalMessage.media}\n`,
`\t| Message Service SID: ${finalMessage.messageservice_sid}\n`,
`\t| Service ID: ${finalMessage.service_id}\n`,
`\t| Parent ID: ${pendingMessagePart.parent_id}\n`,
`\t| User ID: ${finalMessage.user_id}`,
);
if (finalMessage) {
if (message.spokeCreatedAt) {
finalMessage.created_at = message.spokeCreatedAt;
Expand Down
31 changes: 16 additions & 15 deletions src/server/api/conversations.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,20 +187,20 @@ export async function getConversations(
.offset(cursor.offset);
}
console.log(
"getConversations sql",
awsContext && awsContext.awsRequestId,
cursor,
assignmentsFilter,
offsetLimitQuery.toString()
`Org Id: ${organizationId} :: getConversations sql -- \n`,
`\tawsContext: ${awsContext && awsContext.awsRequestId ? true : false}\n`,
`\tcursor: limit=${cursor.limit}, offset=${cursor.offset}\n`,
`\tassignmentsFilter: ${Object.keys(assignmentsFilter).length > 0 ? assignmentsFilter : "no filter"}\n`,
`\toffsetLimitQuery: ${offsetLimitQuery.toString()}`
);

const ccIdRows = await offsetLimitQuery;

console.log(
"getConversations contact ids",
awsContext && awsContext.awsRequestId,
Number(new Date()) - Number(starttime),
ccIdRows.length
`Org Id: ${organizationId} :: getConversations query1 contact ids -- \n`,
`\tawsContext: ${awsContext && awsContext.awsRequestId === undefined ? true : false}\n`,
`\ttime: ${Number(new Date()) - Number(starttime)}ms\n`,
`\tccIdRows length: ${ccIdRows.length}`
);
const ccIds = ccIdRows.map(ccIdRow => {
return ccIdRow.cc_id;
Expand Down Expand Up @@ -254,10 +254,10 @@ export async function getConversations(
query = query.orderBy("cc_id", "desc").orderBy("message.id");
const conversationRows = await query;
console.log(
"getConversations query2 result",
awsContext && awsContext.awsRequestId,
Number(new Date()) - Number(starttime),
conversationRows.length
`Org Id: ${organizationId} :: getConversations query2 conversations -- \n`,
`\tawsContext: ${awsContext && awsContext.awsRequestId === undefined ? true : false}\n`,
`\ttime: ${Number(new Date()) - Number(starttime)}ms\n`,
`\tconversationRows lenght: ${conversationRows.length}`
);
/* collapse the rows to produce an array of objects, with each object
* containing the fields for one conversation, each having an array of
Expand Down Expand Up @@ -320,8 +320,9 @@ export async function getConversations(
/* Query #3 -- get the count of all conversations matching the criteria.
* We need this to show total number of conversations to support paging */
console.log(
"getConversations query3",
Number(new Date()) - Number(starttime)
"getConversations query3 total count + time for total completion of queries\n",
`\ttime: ${Number(new Date()) - Number(starttime)}ms\n`,
`\ttotal conversations: ${conversations.length}`
);
const conversationsCountQuery = getConversationsJoinsAndWhereClause(
r.knexReadOnly,
Expand Down
Loading