Skip to content

Commit d12559f

Browse files
lym953claude
andcommitted
test: invoke twice back-to-back with a single indexing wait
Replaces the two-window/two-5-min-indexing-wait design with one window and one wait, comparing tagged vs. total invocation counts (new getMetricCountWithTag helper) instead of checking existence per window. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent ae2719b commit d12559f

2 files changed

Lines changed: 72 additions & 50 deletions

File tree

Lines changed: 38 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// Verifies the invocations metric has durable_function:true only for a durable function, on
2-
// both the cold-start invocation and a subsequent warm invocation.
3-
import { hasMetricWithTag } from './utils/datadog';
1+
// Verifies the invocations metric has durable_function:true only for a durable function, and
2+
// that the tag persists across a second (warm) invocation instead of only being set on cold start.
3+
import { getMetricCount, getMetricCountWithTag } from './utils/datadog';
44
import { forceColdStart, invokeLambda } from './utils/lambda';
55
import { IDENTIFIER, DEFAULT_DATADOG_INDEXING_WAIT_MS } from '../config';
66

@@ -9,10 +9,8 @@ const stackName = `${IDENTIFIER}-durable-cold-start`;
99
const INVOCATIONS_METRIC = 'aws.lambda.enhanced.invocations';
1010

1111
describe('Durable Function Cold-Start Metric Tag Integration Tests', () => {
12-
let coldStartWindowStart: number;
13-
let coldStartWindowEnd: number;
14-
let warmInvokeWindowStart: number;
15-
let warmInvokeWindowEnd: number;
12+
let windowStart: number;
13+
let windowEnd: number;
1614

1715
const durableFunctionName = `${stackName}-durable-lambda`;
1816
const nonDurableFunctionName = `${stackName}-non-durable-lambda`;
@@ -24,70 +22,60 @@ describe('Durable Function Cold-Start Metric Tag Integration Tests', () => {
2422
invokeLambda(nonDurableFunctionName),
2523
]);
2624

27-
const waitForIndexing = () =>
28-
new Promise((resolve) =>
29-
setTimeout(resolve, DEFAULT_DATADOG_INDEXING_WAIT_MS),
30-
);
31-
3225
beforeAll(async () => {
3326
const functionNames = [durableFunctionName, nonDurableFunctionName];
3427
await Promise.all(functionNames.map((fn) => forceColdStart(fn)));
3528

3629
// Back up 60s so the metric's rollup bucket falls inside the query range.
37-
coldStartWindowStart = Date.now() - 60_000;
38-
await invokeBoth(); // invocation #1 (cold start)
39-
await waitForIndexing();
40-
coldStartWindowEnd = Date.now();
30+
windowStart = Date.now() - 60_000;
31+
32+
// Invoke twice back-to-back (cold start, then warm) and wait for indexing once, rather than
33+
// waiting after each invocation. Whether the tag was set on both invocations (rather than
34+
// only the first) is checked below by comparing tagged vs. total invocation counts.
35+
await invokeBoth();
36+
await invokeBoth();
4137

42-
warmInvokeWindowStart = Date.now() - 60_000;
43-
await invokeBoth(); // invocation #2 (warm)
44-
await waitForIndexing();
45-
warmInvokeWindowEnd = Date.now();
38+
await new Promise((resolve) =>
39+
setTimeout(resolve, DEFAULT_DATADOG_INDEXING_WAIT_MS),
40+
);
41+
windowEnd = Date.now();
4642

47-
console.log('Lambdas invoked twice and indexing waits complete');
48-
}, 3600000);
43+
console.log('Lambdas invoked twice and indexing wait complete');
44+
}, 1800000);
4945

50-
it('durable function cold-start invocation metric should have durable_function:true', async () => {
51-
const hasTag = await hasMetricWithTag(
46+
it('durable function invocation metric should have durable_function:true on every invocation', async () => {
47+
const totalCount = await getMetricCount(
5248
INVOCATIONS_METRIC,
5349
durableFunctionName,
54-
'durable_function:true',
55-
coldStartWindowStart,
56-
coldStartWindowEnd,
50+
windowStart,
51+
windowEnd,
5752
);
58-
expect(hasTag).toBe(true);
59-
});
60-
61-
it('non-durable function cold-start invocation metric should NOT have durable_function:true', async () => {
62-
const hasTag = await hasMetricWithTag(
53+
const taggedCount = await getMetricCountWithTag(
6354
INVOCATIONS_METRIC,
64-
nonDurableFunctionName,
55+
durableFunctionName,
6556
'durable_function:true',
66-
coldStartWindowStart,
67-
coldStartWindowEnd,
57+
windowStart,
58+
windowEnd,
6859
);
69-
expect(hasTag).toBe(false);
60+
expect(totalCount).toBeGreaterThanOrEqual(2);
61+
expect(taggedCount).toBe(totalCount);
7062
});
7163

72-
it('durable function warm invocation metric should still have durable_function:true', async () => {
73-
const hasTag = await hasMetricWithTag(
64+
it('non-durable function invocation metric should NOT have durable_function:true on any invocation', async () => {
65+
const totalCount = await getMetricCount(
7466
INVOCATIONS_METRIC,
75-
durableFunctionName,
76-
'durable_function:true',
77-
warmInvokeWindowStart,
78-
warmInvokeWindowEnd,
67+
nonDurableFunctionName,
68+
windowStart,
69+
windowEnd,
7970
);
80-
expect(hasTag).toBe(true);
81-
});
82-
83-
it('non-durable function warm invocation metric should still NOT have durable_function:true', async () => {
84-
const hasTag = await hasMetricWithTag(
71+
const taggedCount = await getMetricCountWithTag(
8572
INVOCATIONS_METRIC,
8673
nonDurableFunctionName,
8774
'durable_function:true',
88-
warmInvokeWindowStart,
89-
warmInvokeWindowEnd,
75+
windowStart,
76+
windowEnd,
9077
);
91-
expect(hasTag).toBe(false);
78+
expect(totalCount).toBeGreaterThanOrEqual(2);
79+
expect(taggedCount).toBe(0);
9280
});
9381
});

integration-tests/tests/utils/datadog.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,40 @@ export async function getMetricCount(
370370
return pointlist.reduce((acc, [, value]) => acc + (value || 0), 0);
371371
}
372372

373+
/**
374+
* Same as `getMetricCount`, but filtered by an additional tag (e.g. "durable_function:true").
375+
* Used to check whether every emission of a metric over a window carried a given tag, by
376+
* comparing against the untagged `getMetricCount` total for the same window.
377+
*/
378+
export async function getMetricCountWithTag(
379+
metricName: string,
380+
functionName: string,
381+
tagFilter: string,
382+
fromTime: number,
383+
toTime: number,
384+
): Promise<number> {
385+
const baseFunctionName = getServiceName(functionName).toLowerCase();
386+
const query = `sum:${metricName}{functionname:${baseFunctionName},${tagFilter}}.as_count()`;
387+
388+
console.log(`Querying metric count with tag filter: ${query}`);
389+
390+
const response = await requestWithRetry(() => datadogClient.get('/api/v1/query', {
391+
params: {
392+
query,
393+
from: Math.floor(fromTime / 1000),
394+
to: Math.floor(toTime / 1000),
395+
},
396+
}), query);
397+
398+
const series = response.data.series || [];
399+
if (series.length === 0) {
400+
return 0;
401+
}
402+
403+
const pointlist: [number, number][] = series[0].pointlist || [];
404+
return pointlist.reduce((acc, [, value]) => acc + (value || 0), 0);
405+
}
406+
373407
async function getMetrics(
374408
metricName: string,
375409
functionName: string,

0 commit comments

Comments
 (0)