Added logging & metrics to mailgun API calls

refs: https://github.com/TryGhost/Toolbox/issues/439

Adds timed metrics to ensure we know how long Mailgun takes to respond to queries - as well as the status codes we hit.
This commit is contained in:
Sam Lord 2022-10-11 15:11:46 +01:00
parent 1221ba5d1d
commit 6ff34fb49f
3 changed files with 113 additions and 25 deletions

View File

@ -1,6 +1,7 @@
const _ = require('lodash');
const debug = require('@tryghost/debug');
const logging = require('@tryghost/logging');
const metrics = require('@tryghost/metrics');
module.exports = class MailgunClient {
#config;
@ -42,6 +43,7 @@ module.exports = class MailgunClient {
let messageData = {};
let startTime;
try {
const bulkEmailConfig = this.#config.get('bulkEmail');
const messageContent = _.pick(message, 'subject', 'html', 'plaintext');
@ -85,12 +87,22 @@ module.exports = class MailgunClient {
}
const mailgunConfig = this.#getConfig();
startTime = Date.now();
const response = await mailgunInstance.messages.create(mailgunConfig.domain, messageData);
metrics.metric('mailgun-send-mail', {
value: Date.now() - startTime,
statusCode: 200
});
return {
id: response.id
};
} catch (error) {
logging.error(error);
metrics.metric('mailgun-send-mail', {
value: Date.now() - startTime,
statusCode: error.status
});
return Promise.reject({error, messageData});
}
}
@ -106,34 +118,54 @@ module.exports = class MailgunClient {
debug(`fetchEvents: starting fetching first events page`);
const mailgunConfig = this.#getConfig();
let page = await mailgunInstance.events.get(mailgunConfig.domain, mailgunOptions);
let events = page?.items?.map(this.normalizeEvent) || [];
debug(`fetchEvents: finished fetching first page with ${events.length} events`);
let startTime = Date.now();
try {
let page = await mailgunInstance.events.get(mailgunConfig.domain, mailgunOptions);
metrics.metric('mailgun-get-events', {
value: Date.now() - startTime,
statusCode: 200
});
let events = page?.items?.map(this.normalizeEvent) || [];
debug(`fetchEvents: finished fetching first page with ${events.length} events`);
let eventCount = 0;
let eventCount = 0;
pagesLoop:
while (events.length !== 0) {
const batchResult = await batchHandler(events);
pagesLoop:
while (events.length !== 0) {
const batchResult = await batchHandler(events);
result = result.concat(batchResult);
eventCount += events.length;
result = result.concat(batchResult);
eventCount += events.length;
if (eventCount >= maxEvents) {
break pagesLoop;
if (eventCount >= maxEvents) {
break pagesLoop;
}
const nextPageId = page.pages.next.page;
debug(`fetchEvents: starting fetching next page ${nextPageId}`);
startTime = Date.now();
page = await mailgunInstance.events.get(mailgunConfig.domain, {
page: nextPageId,
...mailgunOptions
});
metrics.metric('mailgun-get-events', {
value: Date.now() - startTime,
statusCode: 200
});
events = page?.items?.map(this.normalizeEvent) || [];
debug(`fetchEvents: finished fetching next page with ${events.length} events`);
}
const nextPageId = page.pages.next.page;
debug(`fetchEvents: starting fetching next page ${nextPageId}`);
page = await mailgunInstance.events.get(mailgunConfig.domain, {
page: nextPageId,
...mailgunOptions
return result;
} catch (error) {
// Log and re-throw Mailgun errors
logging.error(error);
metrics.metric('mailgun-get-events', {
value: Date.now() - startTime,
statusCode: error.status
});
events = page?.items?.map(this.normalizeEvent) || [];
debug(`fetchEvents: finished fetching next page with ${events.length} events`);
throw error;
}
return result;
}
normalizeEvent(event) {

View File

@ -26,6 +26,7 @@
"dependencies": {
"@tryghost/debug": "0.1.18",
"@tryghost/logging": "2.3.2",
"@tryghost/metrics": "1.0.16",
"form-data": "4.0.0",
"lodash": "4.17.21",
"mailgun.js": "8.0.1"

View File

@ -4270,7 +4270,7 @@
"@tryghost/root-utils" "^0.3.16"
debug "^4.3.1"
"@tryghost/elasticsearch@^3.0.4":
"@tryghost/elasticsearch@^3.0.2", "@tryghost/elasticsearch@^3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@tryghost/elasticsearch/-/elasticsearch-3.0.4.tgz#f8572122bb34a0192471226d2c5c9e61d049a821"
integrity sha512-ysExjEWI7VXWedmEbi757ub2avPRIZOAvzCWM5XC3vi9FyroW+invABmLfN9jsPX99eGpTWe1ENguslpLEvtdA==
@ -4343,7 +4343,7 @@
resolved "https://registry.yarnpkg.com/@tryghost/http-cache-utils/-/http-cache-utils-0.1.3.tgz#a3a07e55dbe3a62b7d51e98f19c063d03a1ef804"
integrity sha512-QganheP/zhcpFnDLPJYlQ4gBIhd+lAEMh8byx7ocCPM37nuEQ3zlmcM6KzDfUmKYwU+5oI/ya/0Wn0kmnyZ37A==
"@tryghost/http-stream@^0.1.13":
"@tryghost/http-stream@^0.1.10", "@tryghost/http-stream@^0.1.13":
version "0.1.13"
resolved "https://registry.yarnpkg.com/@tryghost/http-stream/-/http-stream-0.1.13.tgz#d7c60e0e6639a4d0c6f9446730ec4c2f8c7347a4"
integrity sha512-SjYFH9RJkU4lsrLwewdhjryBAo+ladUu1yydg6eWtBgdwGZ5z0RmYANxkFL0jkyaw+6U7ntCKMfm6GI8HT7w+Q==
@ -4471,7 +4471,24 @@
lodash "^4.17.21"
luxon "^1.26.0"
"@tryghost/logging@2.2.3", "@tryghost/logging@2.3.2", "@tryghost/logging@^2.2.3":
"@tryghost/logging@2.2.3":
version "2.2.3"
resolved "https://registry.yarnpkg.com/@tryghost/logging/-/logging-2.2.3.tgz#40575a42e18b907a49cee5dfdfa62deb820954aa"
integrity sha512-ACCm84U4HITt3mQhDSpyDLZetxzjYo4ux2MoSVGL3zxPfQBPFoI6hWEiSzYWX/4RGq2l2tR4di+5LWjIe8Ow6A==
dependencies:
"@tryghost/bunyan-rotating-filestream" "^0.0.7"
"@tryghost/elasticsearch" "^3.0.2"
"@tryghost/http-stream" "^0.1.10"
"@tryghost/pretty-stream" "^0.1.11"
"@tryghost/root-utils" "^0.3.15"
bunyan "^1.8.15"
bunyan-loggly "^1.4.2"
fs-extra "^10.0.0"
gelf-stream "^1.1.1"
json-stringify-safe "^5.0.1"
lodash "^4.17.21"
"@tryghost/logging@2.3.2", "@tryghost/logging@^2.2.3":
version "2.3.2"
resolved "https://registry.yarnpkg.com/@tryghost/logging/-/logging-2.3.2.tgz#31559c2f6eebb481a0ee8e9a958b2a2d8d55f82e"
integrity sha512-XIKSNwcG1ARNzSakXXk0jX2Pph3LMHSXQAKAm9q50fKgvX5kMdyHlunmu/NikkFsctOF8MTBGm6BJ97QW3F5IA==
@ -4576,6 +4593,15 @@
chalk "^4.1.0"
sywac "^1.3.0"
"@tryghost/pretty-stream@^0.1.11":
version "0.1.13"
resolved "https://registry.yarnpkg.com/@tryghost/pretty-stream/-/pretty-stream-0.1.13.tgz#392330e57ddb06fd89205eb58726445d5e6c02c8"
integrity sha512-IpSdRxMRJqoy3WUbzwfz1UrBZADAoit24qnRREu71+/lC95ebk0cB2r6Gte2vwiFEuKJ2BFzu7iFRCZeH6jKvg==
dependencies:
lodash "^4.17.21"
moment "^2.29.1"
prettyjson "^1.2.5"
"@tryghost/pretty-stream@^0.1.12":
version "0.1.12"
resolved "https://registry.yarnpkg.com/@tryghost/pretty-stream/-/pretty-stream-0.1.12.tgz#e1991415610142d9895d3e5cb84ac838c58d8c8b"
@ -19319,18 +19345,47 @@ mock-knex@TryGhost/mock-knex#8ecb8c227bf463c991c3d820d33f59efc3ab9682:
lodash "^4.14.2"
semver "^5.3.0"
moment-timezone@0.5.23, moment-timezone@0.5.34, moment-timezone@^0.5.23, moment-timezone@^0.5.31, moment-timezone@^0.5.33:
moment-timezone@0.5.23, moment-timezone@^0.5.23:
version "0.5.23"
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.23.tgz#7cbb00db2c14c71b19303cb47b0fb0a6d8651463"
integrity sha512-WHFH85DkCfiNMDX5D3X7hpNH3/PUhjTGcD0U1SgfBGZxJ3qUmJh5FdvaFjcClxOvB3rzdfj4oRffbI38jEnC1w==
dependencies:
moment ">= 2.9.0"
moment@2.24.0, moment@2.27.0, moment@2.29.1, moment@2.29.4, "moment@>= 2.9.0", moment@^2.10.2, moment@^2.18.1, moment@^2.19.3, moment@^2.27.0, moment@^2.29.1, moment@^2.29.3:
moment-timezone@0.5.34:
version "0.5.34"
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.34.tgz#a75938f7476b88f155d3504a9343f7519d9a405c"
integrity sha512-3zAEHh2hKUs3EXLESx/wsgw6IQdusOT8Bxm3D9UrHPQR7zlMmzwybC8zHEM1tQ4LJwP7fcxrWr8tuBg05fFCbg==
dependencies:
moment ">= 2.9.0"
moment-timezone@^0.5.31, moment-timezone@^0.5.33:
version "0.5.37"
resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.37.tgz#adf97f719c4e458fdb12e2b4e87b8bec9f4eef1e"
integrity sha512-uEDzDNFhfaywRl+vwXxffjjq1q0Vzr+fcQpQ1bU0kbzorfS7zVtZnCnGc8mhWmF39d4g4YriF6kwA75mJKE/Zg==
dependencies:
moment ">= 2.9.0"
moment@2.24.0, "moment@>= 2.9.0", moment@^2.10.2, moment@^2.18.1, moment@^2.19.3:
version "2.24.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
moment@2.27.0:
version "2.27.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.27.0.tgz#8bff4e3e26a236220dfe3e36de756b6ebaa0105d"
integrity sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==
moment@2.29.1:
version "2.29.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
moment@2.29.4, moment@^2.27.0, moment@^2.29.1, moment@^2.29.3:
version "2.29.4"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.4.tgz#3dbe052889fe7c1b2ed966fcb3a77328964ef108"
integrity sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==
moo@^0.5.0, moo@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/moo/-/moo-0.5.1.tgz#7aae7f384b9b09f620b6abf6f74ebbcd1b65dbc4"