qdone 2.2.0 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/commonjs/src/defaults.js +5 -3
- package/commonjs/src/monitor.js +38 -8
- package/commonjs/src/sqs.js +2 -4
- package/package.json +1 -1
- package/src/defaults.js +5 -3
- package/src/monitor.js +41 -8
- package/src/sqs.js +2 -4
package/commonjs/src/defaults.js
CHANGED
|
@@ -94,8 +94,10 @@ function getOptionsWithDefaults(options) {
|
|
|
94
94
|
// For API invocations don't force caller to supply default options
|
|
95
95
|
if (!options)
|
|
96
96
|
options = {};
|
|
97
|
-
// Activate DLQ if any option is set
|
|
98
|
-
|
|
97
|
+
// Activate DLQ if any sub-option is set. Use ?? so that undefined (not
|
|
98
|
+
// passed) falls through to the default, while explicit false is preserved.
|
|
99
|
+
const hasDlqSubOption = !!(options['dlq-suffix'] || options['dlq-after'] || options['dlq-name'] || options.dlqSuffix || options.dlqAfter || options.dlqName);
|
|
100
|
+
const dlq = options.dlq ?? (hasDlqSubOption || undefined);
|
|
99
101
|
const opt = {
|
|
100
102
|
// Shared
|
|
101
103
|
prefix: options.prefix === '' ? options.prefix : (options.prefix || process.env.QDONE_PREFIX || exports.defaults.prefix),
|
|
@@ -124,7 +126,7 @@ function getOptionsWithDefaults(options) {
|
|
|
124
126
|
delay: options.delay || process.env.QDONE_DELAY || exports.defaults.delay,
|
|
125
127
|
sendRetries: options.sendRetries || options['send-retries'] || process.env.QDONE_SEND_RETRIES || exports.defaults.sendRetries,
|
|
126
128
|
failDelay: options.failDelay || options['fail-delay'] || process.env.QDONE_FAIL_DELAY || exports.defaults.failDelay,
|
|
127
|
-
dlq: dlq
|
|
129
|
+
dlq: dlq ?? exports.defaults.dlq,
|
|
128
130
|
dlqSuffix: options.dlqSuffix || options['dlq-suffix'] || process.env.QDONE_DLQ_SUFFIX || exports.defaults.dlqSuffix,
|
|
129
131
|
dlqAfter: options.dlqAfter || options['dlq-after'] || process.env.QDONE_DLQ_AFTER || exports.defaults.dlqAfter,
|
|
130
132
|
tags: options.tags || undefined,
|
package/commonjs/src/monitor.js
CHANGED
|
@@ -8,9 +8,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.monitor = monitor;
|
|
10
10
|
exports.interpretWildcard = interpretWildcard;
|
|
11
|
+
exports.getQueueAge = getQueueAge;
|
|
11
12
|
exports.getAggregateData = getAggregateData;
|
|
12
13
|
const sqs_js_1 = require("./sqs.js");
|
|
13
14
|
const cloudWatch_js_1 = require("./cloudWatch.js");
|
|
15
|
+
const client_cloudwatch_1 = require("@aws-sdk/client-cloudwatch");
|
|
14
16
|
const defaults_js_1 = require("./defaults.js");
|
|
15
17
|
const qrlCache_js_1 = require("./qrlCache.js");
|
|
16
18
|
const debug_1 = __importDefault(require("debug"));
|
|
@@ -45,16 +47,45 @@ function interpretWildcard(queueName) {
|
|
|
45
47
|
// debug({ prefix, suffix, safeSuffix, suffixRegex })
|
|
46
48
|
return { prefix, suffix, safeSuffix, suffixRegex };
|
|
47
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Gets ApproximateAgeOfOldestMessage for a single queue from CloudWatch.
|
|
52
|
+
* This metric is not available via the SQS GetQueueAttributes API.
|
|
53
|
+
*/
|
|
54
|
+
async function getQueueAge(queueName) {
|
|
55
|
+
const now = new Date();
|
|
56
|
+
const params = {
|
|
57
|
+
StartTime: new Date(now.getTime() - 1000 * 60 * 5),
|
|
58
|
+
EndTime: now,
|
|
59
|
+
MetricName: 'ApproximateAgeOfOldestMessage',
|
|
60
|
+
Namespace: 'AWS/SQS',
|
|
61
|
+
Period: 300,
|
|
62
|
+
Dimensions: [{ Name: 'QueueName', Value: queueName }],
|
|
63
|
+
Statistics: ['Maximum']
|
|
64
|
+
};
|
|
65
|
+
const client = (0, cloudWatch_js_1.getCloudWatchClient)();
|
|
66
|
+
const cmd = new client_cloudwatch_1.GetMetricStatisticsCommand(params);
|
|
67
|
+
try {
|
|
68
|
+
const data = await client.send(cmd);
|
|
69
|
+
debug('getQueueAge', queueName, data);
|
|
70
|
+
if (!data.Datapoints || data.Datapoints.length === 0)
|
|
71
|
+
return 0;
|
|
72
|
+
return Math.max(...data.Datapoints.map(d => d.Maximum));
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
debug('getQueueAge error', queueName, e);
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
48
79
|
/**
|
|
49
80
|
* Aggregates inmportant attributes across queues and reports a summary.
|
|
50
|
-
* Attributes:
|
|
81
|
+
* Attributes (from SQS GetQueueAttributes):
|
|
51
82
|
* - ApproximateNumberOfMessages: Sum
|
|
52
83
|
* - ApproximateNumberOfMessagesDelayed: Sum
|
|
53
84
|
* - ApproximateNumberOfMessagesNotVisible: Sum
|
|
85
|
+
* Metrics (from CloudWatch):
|
|
54
86
|
* - ApproximateAgeOfOldestMessage: Max
|
|
55
87
|
*/
|
|
56
88
|
async function getAggregateData(queueName) {
|
|
57
|
-
const maxAttributes = new Set(['ApproximateAgeOfOldestMessage']);
|
|
58
89
|
const { prefix, suffixRegex } = interpretWildcard(queueName);
|
|
59
90
|
const qrls = await (0, sqs_js_1.getMatchingQueues)(prefix, suffixRegex);
|
|
60
91
|
// debug({ qrls })
|
|
@@ -68,15 +99,14 @@ async function getAggregateData(queueName) {
|
|
|
68
99
|
const newAtrribute = parseInt(result.Attributes[key], 10);
|
|
69
100
|
if (newAtrribute > 0) {
|
|
70
101
|
total.contributingQueueNames.add(queue);
|
|
71
|
-
|
|
72
|
-
total[key] = Math.max(total[key] || 0, newAtrribute);
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
total[key] = (total[key] || 0) + newAtrribute;
|
|
76
|
-
}
|
|
102
|
+
total[key] = (total[key] || 0) + newAtrribute;
|
|
77
103
|
}
|
|
78
104
|
}
|
|
79
105
|
}
|
|
106
|
+
// Fetch ApproximateAgeOfOldestMessage from CloudWatch (not available via SQS API)
|
|
107
|
+
// Only query queues with messages to minimize CloudWatch API costs
|
|
108
|
+
const ageResults = await Promise.all([...total.contributingQueueNames].map(queue => getQueueAge(queue)));
|
|
109
|
+
total.ApproximateAgeOfOldestMessage = Math.max(0, ...ageResults);
|
|
80
110
|
// debug({ total })
|
|
81
111
|
// convert set to array
|
|
82
112
|
total.contributingQueueNames = [...total.contributingQueueNames.values()];
|
package/commonjs/src/sqs.js
CHANGED
|
@@ -61,8 +61,7 @@ async function getQueueAttributes(qrls) {
|
|
|
61
61
|
AttributeNames: [
|
|
62
62
|
'ApproximateNumberOfMessages',
|
|
63
63
|
'ApproximateNumberOfMessagesNotVisible',
|
|
64
|
-
'ApproximateNumberOfMessagesDelayed'
|
|
65
|
-
'ApproximateAgeOfOldestMessage'
|
|
64
|
+
'ApproximateNumberOfMessagesDelayed'
|
|
66
65
|
]
|
|
67
66
|
};
|
|
68
67
|
const command = new client_sqs_1.GetQueueAttributesCommand(input);
|
|
@@ -84,8 +83,7 @@ async function getQueueAttributes(qrls) {
|
|
|
84
83
|
Attributes: {
|
|
85
84
|
ApproximateNumberOfMessages: '0',
|
|
86
85
|
ApproximateNumberOfMessagesNotVisible: '0',
|
|
87
|
-
ApproximateNumberOfMessagesDelayed: '0'
|
|
88
|
-
ApproximateAgeOfOldestMessage: '0'
|
|
86
|
+
ApproximateNumberOfMessagesDelayed: '0'
|
|
89
87
|
}
|
|
90
88
|
};
|
|
91
89
|
}
|
package/package.json
CHANGED
package/src/defaults.js
CHANGED
|
@@ -90,8 +90,10 @@ export function getOptionsWithDefaults (options) {
|
|
|
90
90
|
// For API invocations don't force caller to supply default options
|
|
91
91
|
if (!options) options = {}
|
|
92
92
|
|
|
93
|
-
// Activate DLQ if any option is set
|
|
94
|
-
|
|
93
|
+
// Activate DLQ if any sub-option is set. Use ?? so that undefined (not
|
|
94
|
+
// passed) falls through to the default, while explicit false is preserved.
|
|
95
|
+
const hasDlqSubOption = !!(options['dlq-suffix'] || options['dlq-after'] || options['dlq-name'] || options.dlqSuffix || options.dlqAfter || options.dlqName)
|
|
96
|
+
const dlq = options.dlq ?? (hasDlqSubOption || undefined)
|
|
95
97
|
|
|
96
98
|
const opt = {
|
|
97
99
|
// Shared
|
|
@@ -123,7 +125,7 @@ export function getOptionsWithDefaults (options) {
|
|
|
123
125
|
delay: options.delay || process.env.QDONE_DELAY || defaults.delay,
|
|
124
126
|
sendRetries: options.sendRetries || options['send-retries'] || process.env.QDONE_SEND_RETRIES || defaults.sendRetries,
|
|
125
127
|
failDelay: options.failDelay || options['fail-delay'] || process.env.QDONE_FAIL_DELAY || defaults.failDelay,
|
|
126
|
-
dlq: dlq
|
|
128
|
+
dlq: dlq ?? defaults.dlq,
|
|
127
129
|
dlqSuffix: options.dlqSuffix || options['dlq-suffix'] || process.env.QDONE_DLQ_SUFFIX || defaults.dlqSuffix,
|
|
128
130
|
dlqAfter: options.dlqAfter || options['dlq-after'] || process.env.QDONE_DLQ_AFTER || defaults.dlqAfter,
|
|
129
131
|
tags: options.tags || undefined,
|
package/src/monitor.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { getMatchingQueues, getQueueAttributes } from './sqs.js'
|
|
6
|
-
import { putAggregateData } from './cloudWatch.js'
|
|
6
|
+
import { putAggregateData, getCloudWatchClient } from './cloudWatch.js'
|
|
7
|
+
import { GetMetricStatisticsCommand } from '@aws-sdk/client-cloudwatch'
|
|
7
8
|
import { getOptionsWithDefaults } from './defaults.js'
|
|
8
9
|
import { normalizeQueueName } from './qrlCache.js'
|
|
9
10
|
import Debug from 'debug'
|
|
@@ -38,16 +39,44 @@ export function interpretWildcard (queueName) {
|
|
|
38
39
|
return { prefix, suffix, safeSuffix, suffixRegex }
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Gets ApproximateAgeOfOldestMessage for a single queue from CloudWatch.
|
|
44
|
+
* This metric is not available via the SQS GetQueueAttributes API.
|
|
45
|
+
*/
|
|
46
|
+
export async function getQueueAge (queueName) {
|
|
47
|
+
const now = new Date()
|
|
48
|
+
const params = {
|
|
49
|
+
StartTime: new Date(now.getTime() - 1000 * 60 * 5),
|
|
50
|
+
EndTime: now,
|
|
51
|
+
MetricName: 'ApproximateAgeOfOldestMessage',
|
|
52
|
+
Namespace: 'AWS/SQS',
|
|
53
|
+
Period: 300,
|
|
54
|
+
Dimensions: [{ Name: 'QueueName', Value: queueName }],
|
|
55
|
+
Statistics: ['Maximum']
|
|
56
|
+
}
|
|
57
|
+
const client = getCloudWatchClient()
|
|
58
|
+
const cmd = new GetMetricStatisticsCommand(params)
|
|
59
|
+
try {
|
|
60
|
+
const data = await client.send(cmd)
|
|
61
|
+
debug('getQueueAge', queueName, data)
|
|
62
|
+
if (!data.Datapoints || data.Datapoints.length === 0) return 0
|
|
63
|
+
return Math.max(...data.Datapoints.map(d => d.Maximum))
|
|
64
|
+
} catch (e) {
|
|
65
|
+
debug('getQueueAge error', queueName, e)
|
|
66
|
+
return 0
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
41
70
|
/**
|
|
42
71
|
* Aggregates inmportant attributes across queues and reports a summary.
|
|
43
|
-
* Attributes:
|
|
72
|
+
* Attributes (from SQS GetQueueAttributes):
|
|
44
73
|
* - ApproximateNumberOfMessages: Sum
|
|
45
74
|
* - ApproximateNumberOfMessagesDelayed: Sum
|
|
46
75
|
* - ApproximateNumberOfMessagesNotVisible: Sum
|
|
76
|
+
* Metrics (from CloudWatch):
|
|
47
77
|
* - ApproximateAgeOfOldestMessage: Max
|
|
48
78
|
*/
|
|
49
79
|
export async function getAggregateData (queueName) {
|
|
50
|
-
const maxAttributes = new Set(['ApproximateAgeOfOldestMessage'])
|
|
51
80
|
const { prefix, suffixRegex } = interpretWildcard(queueName)
|
|
52
81
|
const qrls = await getMatchingQueues(prefix, suffixRegex)
|
|
53
82
|
// debug({ qrls })
|
|
@@ -61,14 +90,18 @@ export async function getAggregateData (queueName) {
|
|
|
61
90
|
const newAtrribute = parseInt(result.Attributes[key], 10)
|
|
62
91
|
if (newAtrribute > 0) {
|
|
63
92
|
total.contributingQueueNames.add(queue)
|
|
64
|
-
|
|
65
|
-
total[key] = Math.max(total[key] || 0, newAtrribute)
|
|
66
|
-
} else {
|
|
67
|
-
total[key] = (total[key] || 0) + newAtrribute
|
|
68
|
-
}
|
|
93
|
+
total[key] = (total[key] || 0) + newAtrribute
|
|
69
94
|
}
|
|
70
95
|
}
|
|
71
96
|
}
|
|
97
|
+
|
|
98
|
+
// Fetch ApproximateAgeOfOldestMessage from CloudWatch (not available via SQS API)
|
|
99
|
+
// Only query queues with messages to minimize CloudWatch API costs
|
|
100
|
+
const ageResults = await Promise.all(
|
|
101
|
+
[...total.contributingQueueNames].map(queue => getQueueAge(queue))
|
|
102
|
+
)
|
|
103
|
+
total.ApproximateAgeOfOldestMessage = Math.max(0, ...ageResults)
|
|
104
|
+
|
|
72
105
|
// debug({ total })
|
|
73
106
|
// convert set to array
|
|
74
107
|
total.contributingQueueNames = [...total.contributingQueueNames.values()]
|
package/src/sqs.js
CHANGED
|
@@ -55,8 +55,7 @@ export async function getQueueAttributes (qrls) {
|
|
|
55
55
|
AttributeNames: [
|
|
56
56
|
'ApproximateNumberOfMessages',
|
|
57
57
|
'ApproximateNumberOfMessagesNotVisible',
|
|
58
|
-
'ApproximateNumberOfMessagesDelayed'
|
|
59
|
-
'ApproximateAgeOfOldestMessage'
|
|
58
|
+
'ApproximateNumberOfMessagesDelayed'
|
|
60
59
|
]
|
|
61
60
|
}
|
|
62
61
|
const command = new GetQueueAttributesCommand(input)
|
|
@@ -77,8 +76,7 @@ export async function getQueueAttributes (qrls) {
|
|
|
77
76
|
Attributes: {
|
|
78
77
|
ApproximateNumberOfMessages: '0',
|
|
79
78
|
ApproximateNumberOfMessagesNotVisible: '0',
|
|
80
|
-
ApproximateNumberOfMessagesDelayed: '0'
|
|
81
|
-
ApproximateAgeOfOldestMessage: '0'
|
|
79
|
+
ApproximateNumberOfMessagesDelayed: '0'
|
|
82
80
|
}
|
|
83
81
|
}
|
|
84
82
|
}
|