Skip to content

Commit 1eff500

Browse files
authored
fix: Allow non-integral latency thresholds and durations (#587)
Fixes #586. Adds the `integral: false` option to [`Duration.toMillisecond()`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.Duration.html#towbrmillisecondsopts) calls to allow the original non-integral/sub-millisecond threshold values to be provided to CloudWatch. These four lines are the only uses of `toMilliseconds` in the package. I also created a new test for the `LatencyAlarmFactory` class to test these specific cases. To verify that they were working, I ran the tests without the fix in place and got the expected error messages: [gist](https://gist.github.com/sajidanw/37fd1ddd63ff763a911bb3a1cf58b2b8). --- _By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license_
1 parent fb22a52 commit 1eff500

File tree

2 files changed

+71
-4
lines changed

2 files changed

+71
-4
lines changed

lib/common/monitoring/alarms/LatencyAlarmFactory.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ export class LatencyAlarmFactory {
166166
ComparisonOperator.GREATER_THAN_THRESHOLD,
167167
...props,
168168
disambiguator,
169-
threshold: props.maxLatency.toMilliseconds(),
169+
threshold: props.maxLatency.toMilliseconds({ integral: false }),
170170
alarmNameSuffix,
171171
// we will dedupe any kind of latency issue to the same ticket
172172
alarmDedupeStringSuffix: this.alarmFactory
@@ -200,7 +200,7 @@ export class LatencyAlarmFactory {
200200
ComparisonOperator.GREATER_THAN_THRESHOLD,
201201
...props,
202202
disambiguator,
203-
threshold: props.maxLatency.toMilliseconds(),
203+
threshold: props.maxLatency.toMilliseconds({ integral: false }),
204204
alarmNameSuffix,
205205
// we will dedupe any kind of latency issue to the same alarm
206206
alarmDedupeStringSuffix: this.alarmFactory
@@ -230,7 +230,7 @@ export class LatencyAlarmFactory {
230230
ComparisonOperator.GREATER_THAN_THRESHOLD,
231231
...props,
232232
disambiguator,
233-
threshold: props.maxDuration.toMilliseconds(),
233+
threshold: props.maxDuration.toMilliseconds({ integral: false }),
234234
alarmNameSuffix,
235235
// we will dedupe any kind of latency issue to the same ticket
236236
alarmDedupeStringSuffix: this.alarmFactory
@@ -264,7 +264,7 @@ export class LatencyAlarmFactory {
264264
ComparisonOperator.GREATER_THAN_THRESHOLD,
265265
...props,
266266
disambiguator,
267-
threshold: props.maxDuration.toMilliseconds(),
267+
threshold: props.maxDuration.toMilliseconds({ integral: false }),
268268
alarmNameSuffix,
269269
// we will dedupe any kind of latency issue to the same ticket
270270
alarmDedupeStringSuffix: this.alarmFactory
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { Duration, Stack } from "aws-cdk-lib";
2+
import { Metric } from "aws-cdk-lib/aws-cloudwatch";
3+
import { Construct } from "constructs";
4+
5+
import {
6+
AlarmFactory,
7+
AlarmFactoryDefaults,
8+
LatencyAlarmFactory,
9+
LatencyType,
10+
MetricFactoryDefaults,
11+
noopAction,
12+
} from "../../../lib";
13+
14+
const stack = new Stack();
15+
const construct = new Construct(stack, "SampleConstruct");
16+
17+
const globalMetricDefaults: MetricFactoryDefaults = {
18+
namespace: "DummyNamespace",
19+
};
20+
const globalAlarmDefaults: AlarmFactoryDefaults = {
21+
alarmNamePrefix: "DummyServiceAlarms",
22+
actionsEnabled: true,
23+
datapointsToAlarm: 6,
24+
// we do not care about alarm actions in this test
25+
action: noopAction(),
26+
};
27+
const factory = new AlarmFactory(construct, {
28+
globalMetricDefaults,
29+
globalAlarmDefaults,
30+
localAlarmNamePrefix: "prefix",
31+
});
32+
33+
const metric = new Metric({
34+
metricName: "DummyMetric1",
35+
namespace: "DummyCustomNamespace",
36+
dimensionsMap: { CustomDimension: "CustomDimensionValue" },
37+
});
38+
39+
const latencyAlarmFactory = new LatencyAlarmFactory(factory);
40+
41+
test("addLatencyAlarm: non-integral millisecond thresholds do not throw error", () => {
42+
latencyAlarmFactory.addLatencyAlarm(metric, LatencyType.P99, {
43+
maxLatency: Duration.millis(0.5),
44+
});
45+
});
46+
47+
test("addIntegrationLatencyAlarm: non-integral millisecond thresholds do not throw error", () => {
48+
latencyAlarmFactory.addIntegrationLatencyAlarm(metric, LatencyType.P99, {
49+
maxLatency: Duration.millis(2.5),
50+
});
51+
});
52+
53+
test("addDurationAlarm: non-integral millisecond durations do not throw error", () => {
54+
latencyAlarmFactory.addDurationAlarm(metric, LatencyType.P99, {
55+
maxDuration: Duration.millis(0.5),
56+
});
57+
});
58+
59+
test("addJvmGarbageCollectionDurationAlarm: non-integral millisecond durations do not throw error", () => {
60+
latencyAlarmFactory.addJvmGarbageCollectionDurationAlarm(
61+
metric,
62+
LatencyType.P99,
63+
{
64+
maxDuration: Duration.millis(2.5),
65+
},
66+
);
67+
});

0 commit comments

Comments
 (0)