Skip to content

Commit 021acfd

Browse files
authored
Merge pull request #31 from DataDog/stephenf/add-runtime-and-memorysize-tags
Add runtime and memorysize tags to enhanced metrics
2 parents 6b94ed5 + c83d1db commit 021acfd

File tree

7 files changed

+126
-15
lines changed

7 files changed

+126
-15
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ If you have the Datadog Lambda Log forwarder enabled and are sending custom metr
8181

8282
### DD_ENHANCED_METRICS
8383

84-
If you set the value of this variable to "true" then the Lambda layer will increment a Lambda integration metric called `aws.lambda.enhanced.invocations` with each invocation and `aws.lambda.enhanced.errors` if the invocation results in an error. These metrics are tagged with the function name, region, and account, as well as `cold_start:true|false`.
84+
If you set the value of this variable to "true" then the Lambda layer will increment a Lambda integration metric called `aws.lambda.enhanced.invocations` with each invocation and `aws.lambda.enhanced.errors` if the invocation results in an error. These metrics are tagged with the function name, region, account, runtime, memorysize, and `cold_start:true|false`.
8585

8686
## Usage
8787

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "datadog-lambda-js",
3-
"version": "0.6.0",
3+
"version": "0.7.0",
44
"description": "Lambda client library that supports hybrid tracing in node js",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

src/index.spec.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ describe("datadog", () => {
189189
await wrapped({}, mockContext, () => {});
190190

191191
expect(mockedIncrementInvocations).toBeCalledTimes(1);
192-
expect(mockedIncrementInvocations).toBeCalledWith(mockARN);
192+
expect(mockedIncrementInvocations).toBeCalledWith(mockContext);
193193

194194
await wrapped({}, mockContext, () => {});
195195
await wrapped({}, mockContext, () => {});
@@ -213,8 +213,8 @@ describe("datadog", () => {
213213
expect(mockedIncrementInvocations).toBeCalledTimes(1);
214214
expect(mockedIncrementErrors).toBeCalledTimes(1);
215215

216-
expect(mockedIncrementInvocations).toBeCalledWith(mockARN);
217-
expect(mockedIncrementErrors).toBeCalledWith(mockARN);
216+
expect(mockedIncrementInvocations).toBeCalledWith(mockContext);
217+
expect(mockedIncrementErrors).toBeCalledWith(mockContext);
218218
});
219219

220220
it("increments errors and invocations with config setting", async () => {
@@ -230,8 +230,8 @@ describe("datadog", () => {
230230
expect(mockedIncrementInvocations).toBeCalledTimes(1);
231231
expect(mockedIncrementErrors).toBeCalledTimes(1);
232232

233-
expect(mockedIncrementInvocations).toBeCalledWith(mockARN);
234-
expect(mockedIncrementErrors).toBeCalledWith(mockARN);
233+
expect(mockedIncrementInvocations).toBeCalledWith(mockContext);
234+
expect(mockedIncrementErrors).toBeCalledWith(mockContext);
235235
});
236236

237237
it("doesn't increment enhanced metrics without env var or config", async () => {

src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,12 @@ export function datadog<TEvent, TResult>(
8181
listener.onStartInvocation(event, context);
8282
}
8383
if (finalConfig.enhancedMetrics) {
84-
incrementInvocationsMetric(context.invokedFunctionArn);
84+
incrementInvocationsMetric(context);
8585
}
8686
},
8787
async (event, context, error?) => {
8888
if (finalConfig.enhancedMetrics && error) {
89-
incrementErrorsMetric(context.invokedFunctionArn);
89+
incrementErrorsMetric(context);
9090
}
9191
// Completion hook, (called once per handler invocation)
9292
for (const listener of listeners) {

src/metrics/enhanced-metrics.spec.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { Context } from "aws-lambda";
2+
import { _resetColdStart } from "../utils/cold-start";
3+
import { getProcessVersion } from "../utils/process-version";
4+
import { getEnhancedMetricTags, getRuntimeTag } from "./enhanced-metrics";
5+
6+
jest.mock("../utils/process-version");
7+
8+
const mockedGetProcessVersion = getProcessVersion as jest.Mock<string>;
9+
10+
const mockARN = "arn:aws:lambda:us-east-1:123497598159:function:my-test-lambda";
11+
const mockContext = ({
12+
invokedFunctionArn: mockARN,
13+
memoryLimitInMB: "128",
14+
} as any) as Context;
15+
16+
describe("getRuntimeTag", () => {
17+
it("returns a null runtime tag when version is not recognized", () => {
18+
mockedGetProcessVersion.mockReturnValue("v6.2.3");
19+
expect(getRuntimeTag()).toBe(null);
20+
});
21+
22+
it("returns the expected tag for v8.10", () => {
23+
mockedGetProcessVersion.mockReturnValue("v8.10.0");
24+
expect(getRuntimeTag()).toBe("runtime:nodejs8.10");
25+
});
26+
27+
it("returns the expected tag for v10.x", () => {
28+
mockedGetProcessVersion.mockReturnValue("v10.1.0");
29+
expect(getRuntimeTag()).toBe("runtime:nodejs10.x");
30+
});
31+
});
32+
33+
describe("getEnhancedMetricTags", () => {
34+
beforeEach(() => {
35+
_resetColdStart();
36+
});
37+
afterEach(() => {
38+
_resetColdStart();
39+
});
40+
41+
it("generates tag list with runtime", () => {
42+
mockedGetProcessVersion.mockReturnValue("v8.10.0");
43+
expect(getEnhancedMetricTags(mockContext)).toStrictEqual([
44+
"region:us-east-1",
45+
"account_id:123497598159",
46+
"functionname:my-test-lambda",
47+
"cold_start:true",
48+
"memorysize:128",
49+
"runtime:nodejs8.10",
50+
]);
51+
});
52+
53+
it("doesn't add runtime tag if version is unrecognized", () => {
54+
mockedGetProcessVersion.mockReturnValue("v6.3.2");
55+
expect(getEnhancedMetricTags(mockContext)).toStrictEqual([
56+
"region:us-east-1",
57+
"account_id:123497598159",
58+
"functionname:my-test-lambda",
59+
"cold_start:true",
60+
"memorysize:128",
61+
]);
62+
});
63+
});

src/metrics/enhanced-metrics.ts

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,61 @@
11
import { getEnvValue, sendDistributionMetric } from "../index";
22

3+
import { Context } from "aws-lambda";
34
import { parseTagsFromARN } from "../utils/arn";
45
import { getColdStartTag } from "../utils/cold-start";
6+
import { getProcessVersion } from "../utils/process-version";
57

68
const ENHANCED_LAMBDA_METRICS_NAMESPACE = "aws.lambda.enhanced";
79

8-
export function incrementInvocationsMetric(functionARN: string): void {
9-
const tags = [...parseTagsFromARN(functionARN), getColdStartTag()];
10-
sendDistributionMetric(`${ENHANCED_LAMBDA_METRICS_NAMESPACE}.invocations`, 1, ...tags);
10+
// Same tag strings added to normal Lambda integration metrics
11+
enum RuntimeTagValues {
12+
Node8 = "nodejs8.10",
13+
Node10 = "nodejs10.x",
1114
}
1215

13-
export function incrementErrorsMetric(functionARN: string): void {
14-
const tags = [...parseTagsFromARN(functionARN), getColdStartTag()];
15-
sendDistributionMetric(`${ENHANCED_LAMBDA_METRICS_NAMESPACE}.errors`, 1, ...tags);
16+
/**
17+
* Uses process.version to create a runtime tag
18+
* If a version cannot be identified, returns null
19+
* See https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html
20+
*/
21+
export function getRuntimeTag(): string | null {
22+
const processVersion = getProcessVersion();
23+
let processVersionTagString: string | null = null;
24+
25+
if (processVersion.startsWith("v8.10")) {
26+
processVersionTagString = RuntimeTagValues.Node8;
27+
}
28+
29+
if (processVersion.startsWith("v10")) {
30+
processVersionTagString = RuntimeTagValues.Node10;
31+
}
32+
33+
if (!processVersionTagString) {
34+
return null;
35+
}
36+
37+
return `runtime:${processVersionTagString}`;
38+
}
39+
40+
export function getEnhancedMetricTags(context: Context): string[] {
41+
const tags = [
42+
...parseTagsFromARN(context.invokedFunctionArn),
43+
getColdStartTag(),
44+
`memorysize:${context.memoryLimitInMB}`,
45+
];
46+
47+
const runtimeTag = getRuntimeTag();
48+
if (runtimeTag) {
49+
tags.push(runtimeTag);
50+
}
51+
52+
return tags;
53+
}
54+
55+
export function incrementInvocationsMetric(context: Context): void {
56+
sendDistributionMetric(`${ENHANCED_LAMBDA_METRICS_NAMESPACE}.invocations`, 1, ...getEnhancedMetricTags(context));
57+
}
58+
59+
export function incrementErrorsMetric(context: Context): void {
60+
sendDistributionMetric(`${ENHANCED_LAMBDA_METRICS_NAMESPACE}.errors`, 1, ...getEnhancedMetricTags(context));
1661
}

src/utils/process-version.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function getProcessVersion() {
2+
return process.version;
3+
}

0 commit comments

Comments
 (0)