Skip to content

Commit 41a8d0b

Browse files
authored
Merge pull request #50 from DataDog/stephenf/log-enhanced-metrics-by-default-js
Enable enhanced metrics by default and write enhanced metrics to logs
2 parents 047c793 + 51f4033 commit 41a8d0b

File tree

9 files changed

+61
-34
lines changed

9 files changed

+61
-34
lines changed

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.14.0",
3+
"version": "1.15.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: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,7 @@ describe("datadog", () => {
225225
expect(spy).toHaveBeenCalledWith("[dd.trace_id=123456 dd.span_id=9101112] Hello");
226226
});
227227

228-
it("increments invocations for each function call with env var", async () => {
229-
process.env.DD_ENHANCED_METRICS = "true";
228+
it("increments invocations for each function call", async () => {
230229
const wrapped = datadog(handler);
231230

232231
await wrapped({}, mockContext, () => {});
@@ -241,9 +240,7 @@ describe("datadog", () => {
241240
expect(mockedIncrementInvocations).toBeCalledTimes(4);
242241
});
243242

244-
it("increments errors correctly with env var", async () => {
245-
process.env.DD_ENHANCED_METRICS = "true";
246-
243+
it("increments errors enhanced metric", async () => {
247244
const handlerError: Handler = (event, context, callback) => {
248245
throw Error("Some error");
249246
};
@@ -260,24 +257,23 @@ describe("datadog", () => {
260257
expect(mockedIncrementErrors).toBeCalledWith(mockContext);
261258
});
262259

263-
it("increments errors and invocations with config setting", async () => {
260+
it("doesn't increment errors or invocations with config false setting", async () => {
264261
const handlerError: Handler = (event, context, callback) => {
265262
throw Error("Some error");
266263
};
267264

268-
const wrappedHandler = datadog(handlerError, { enhancedMetrics: true });
265+
const wrappedHandler = datadog(handlerError, { enhancedMetrics: false });
269266

270267
const result = wrappedHandler({}, mockContext, () => {});
271268
await expect(result).rejects.toEqual(Error("Some error"));
272269

273-
expect(mockedIncrementInvocations).toBeCalledTimes(1);
274-
expect(mockedIncrementErrors).toBeCalledTimes(1);
275-
276-
expect(mockedIncrementInvocations).toBeCalledWith(mockContext);
277-
expect(mockedIncrementErrors).toBeCalledWith(mockContext);
270+
expect(mockedIncrementInvocations).toBeCalledTimes(0);
271+
expect(mockedIncrementErrors).toBeCalledTimes(0);
278272
});
279273

280-
it("doesn't increment enhanced metrics without env var or config", async () => {
274+
it("doesn't increment enhanced metrics with env var set to false", async () => {
275+
process.env.DD_ENHANCED_METRICS = "false";
276+
281277
const handlerError: Handler = (event, context, callback) => {
282278
throw Error("Some error");
283279
};

src/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export const defaultConfig: Config = {
4040
apiKeyKMS: "",
4141
autoPatchHTTP: true,
4242
debugLogging: false,
43-
enhancedMetrics: false,
43+
enhancedMetrics: true,
4444
injectLogContext: false,
4545
logForwarding: false,
4646
mergeDatadogXrayTraces: false,
@@ -166,7 +166,7 @@ function getConfig(userConfig?: Partial<Config>): Config {
166166
config.logForwarding = result === "true";
167167
}
168168
if (userConfig === undefined || userConfig.enhancedMetrics === undefined) {
169-
const result = getEnvValue(enhancedMetricsEnvVar, "false").toLowerCase();
169+
const result = getEnvValue(enhancedMetricsEnvVar, "true").toLowerCase();
170170
config.enhancedMetrics = result === "true";
171171
}
172172

src/metrics/build-metric-log.ts

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/metrics/enhanced-metrics.spec.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ describe("getRuntimeTag", () => {
2828
mockedGetProcessVersion.mockReturnValue("v10.1.0");
2929
expect(getRuntimeTag()).toBe("runtime:nodejs10.x");
3030
});
31+
32+
it("returns the right tag for v12.13.0", () => {
33+
mockedGetProcessVersion.mockReturnValue("v12.13.0");
34+
expect(getRuntimeTag()).toBe("runtime:nodejs12.x");
35+
});
3136
});
3237

3338
describe("getEnhancedMetricTags", () => {

src/metrics/enhanced-metrics.ts

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

33
import { Context } from "aws-lambda";
44
import { parseTagsFromARN } from "../utils/arn";
55
import { getColdStartTag } from "../utils/cold-start";
66
import { getProcessVersion } from "../utils/process-version";
7+
import { writeMetricToStdout } from "./metric-log";
78

89
const ENHANCED_LAMBDA_METRICS_NAMESPACE = "aws.lambda.enhanced";
910

1011
// Same tag strings added to normal Lambda integration metrics
1112
enum RuntimeTagValues {
1213
Node8 = "nodejs8.10",
1314
Node10 = "nodejs10.x",
15+
Node12 = "nodejs12.x",
1416
}
1517

1618
/**
@@ -30,6 +32,10 @@ export function getRuntimeTag(): string | null {
3032
processVersionTagString = RuntimeTagValues.Node10;
3133
}
3234

35+
if (processVersion.startsWith("v12")) {
36+
processVersionTagString = RuntimeTagValues.Node12;
37+
}
38+
3339
if (!processVersionTagString) {
3440
return null;
3541
}
@@ -52,10 +58,20 @@ export function getEnhancedMetricTags(context: Context): string[] {
5258
return tags;
5359
}
5460

61+
/**
62+
* Increments the specified enhanced metric, applying all relevant tags
63+
* @param context object passed to invocation by AWS
64+
* @param metricName name of the enhanced metric without namespace prefix, i.e. "invocations" or "errors"
65+
*/
66+
function incrementEnhancedMetric(metricName: string, context: Context) {
67+
// Always write enhanced metrics to standard out
68+
writeMetricToStdout(`${ENHANCED_LAMBDA_METRICS_NAMESPACE}.${metricName}`, 1, getEnhancedMetricTags(context));
69+
}
70+
5571
export function incrementInvocationsMetric(context: Context): void {
56-
sendDistributionMetric(`${ENHANCED_LAMBDA_METRICS_NAMESPACE}.invocations`, 1, ...getEnhancedMetricTags(context));
72+
incrementEnhancedMetric("invocations", context);
5773
}
5874

5975
export function incrementErrorsMetric(context: Context): void {
60-
sendDistributionMetric(`${ENHANCED_LAMBDA_METRICS_NAMESPACE}.errors`, 1, ...getEnhancedMetricTags(context));
76+
incrementEnhancedMetric("errors", context);
6177
}

src/metrics/listener.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { promisify } from "util";
22

33
import { logDebug, logError } from "../utils";
44
import { APIClient } from "./api";
5-
import { buildMetricLog } from "./build-metric-log";
65
import { KMSService } from "./kms-service";
6+
import { writeMetricToStdout } from "./metric-log";
77
import { Distribution } from "./model";
88
import { Processor } from "./processor";
99

@@ -85,9 +85,7 @@ export class MetricsListener {
8585

8686
public sendDistributionMetric(name: string, value: number, ...tags: string[]) {
8787
if (this.config.logForwarding) {
88-
// We use process.stdout.write, because console.log will prepend metadata to the start
89-
// of the log that log forwarder doesn't know how to read.
90-
process.stdout.write(buildMetricLog(name, value, tags));
88+
writeMetricToStdout(name, value, tags);
9189
return;
9290
}
9391
const dist = new Distribution(name, [{ timestamp: new Date(), value }], ...tags);

src/metrics/build-metric-log.spec.ts renamed to src/metrics/metric-log.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { buildMetricLog } from "./build-metric-log";
1+
import { buildMetricLog } from "./metric-log";
22

33
describe("buildMetricLog", () => {
44
jest.spyOn(Date, "now").mockImplementation(() => 1487076708123);

src/metrics/metric-log.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Builds the string representation of the metric that will be written to logs
2+
export function buildMetricLog(name: string, value: number, tags: string[]) {
3+
return `${JSON.stringify({
4+
// Date.now() returns Unix time in milliseconds, we convert to seconds for DD API submission
5+
e: Date.now() / 1000,
6+
m: name,
7+
t: tags,
8+
v: value,
9+
})}\n`;
10+
}
11+
12+
/**
13+
* Writes the specified metric to standard output
14+
* @param name The name of the metric
15+
* @param value Metric datapoint's value
16+
* @param tags Tags to apply to the metric
17+
*/
18+
export function writeMetricToStdout(name: string, value: number, tags: string[]) {
19+
// We use process.stdout.write, because console.log will prepend metadata to the start
20+
// of the log that log forwarder doesn't know how to read.
21+
process.stdout.write(buildMetricLog(name, value, tags));
22+
}

0 commit comments

Comments
 (0)