From 4107fee0a5ec1f65e07162132b3c1ced596c676e Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Fri, 28 Jun 2024 10:30:58 -0400 Subject: [PATCH 01/11] tags for API metrics --- src/index.ts | 17 +++++++++++++++-- src/metrics/batcher.ts | 6 ++---- src/metrics/listener.ts | 16 ++++++++++++++-- src/metrics/model.ts | 7 +++++-- src/metrics/processor.ts | 10 +++++----- 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/src/index.ts b/src/index.ts index c3715aa0..fb5525de 100644 --- a/src/index.ts +++ b/src/index.ts @@ -153,7 +153,7 @@ export function datadog( try { await traceListener.onStartInvocation(event, context); - await metricsListener.onStartInvocation(event); + await metricsListener.onStartInvocation(event, context); if (finalConfig.enhancedMetrics) { incrementInvocationsMetric(metricsListener, context); } @@ -267,7 +267,7 @@ export function extractArgs(isResponseStreamFunction: boolean, ...args: * @param tags The tags associated with the metric. Should be of the format "tag:value". */ export function sendDistributionMetricWithDate(name: string, value: number, metricTime: Date, ...tags: string[]) { - tags = [...tags, getRuntimeTag()]; + tags = [...tags, getRuntimeTag(), ...getDDTags()]; if (currentMetricsListener !== undefined) { currentMetricsListener.sendDistributionMetricWithDate(name, value, metricTime, false, ...tags); @@ -419,6 +419,19 @@ function getRuntimeTag(): string { return `dd_lambda_layer:datadog-node${version}`; } +function getDDTags(): string[] { + const ddTags = getEnvValue("DD_TAGS", "").split(","); + const ddService = getEnvValue("DD_SERVICE", "") + if (ddService.length > 0) { + ddTags.push(`service:${ddService}`) + } + const ddEnv = getEnvValue("DD_ENV", "") + if (ddEnv.length > 0) { + ddTags.push(`env:${ddEnv}`) + } + return ddTags; +} + export async function emitTelemetryOnErrorOutsideHandler( error: Error, functionName: string, diff --git a/src/metrics/batcher.ts b/src/metrics/batcher.ts index 2c70c131..bc872679 100644 --- a/src/metrics/batcher.ts +++ b/src/metrics/batcher.ts @@ -22,10 +22,8 @@ export class Batcher { /** * Convert batched metrics to a list of api compatible metrics */ - public toAPIMetrics(): APIMetric[] { - return [...this.metrics.values()] - .map((metric) => metric.toAPIMetrics()) // No flatMap support yet in node 10 - .reduce((prev, curr) => prev.concat(curr), []); + public toAPIMetrics(tags?: string[]): APIMetric[] { + return [...this.metrics.values()].flatMap((metric) => metric.toAPIMetrics(tags)) } private getBatchKey(metric: Metric): string { diff --git a/src/metrics/listener.ts b/src/metrics/listener.ts index c8e4100c..40f31ebb 100644 --- a/src/metrics/listener.ts +++ b/src/metrics/listener.ts @@ -5,6 +5,8 @@ import { flushExtension, isExtensionRunning } from "./extension"; import { KMSService } from "./kms-service"; import { writeMetricToStdout } from "./metric-log"; import { Distribution } from "./model"; +import { Context } from "aws-lambda"; +import { getEnhancedMetricTags } from "./enhanced-metrics"; const METRICS_BATCH_SEND_INTERVAL = 10000; // 10 seconds @@ -58,13 +60,15 @@ export class MetricsListener { private apiKey: Promise; private statsDClient?: StatsD; private isExtensionRunning?: boolean = undefined; + private globalTags?: string[] = []; constructor(private kmsClient: KMSService, private config: MetricsConfig) { this.apiKey = this.getAPIKey(config); this.config = config; } - public async onStartInvocation(_: any) { + public async onStartInvocation(_: any, context?: Context) { + this.globalTags = this.getGlobalTags(context); if (this.isExtensionRunning === undefined) { this.isExtensionRunning = await isExtensionRunning(); logDebug(`Extension present: ${this.isExtensionRunning}`); @@ -183,7 +187,7 @@ export class MetricsListener { const url = `https://api.${config.siteURL}`; const apiClient = new APIClient(key, url); const processor = new Processor(apiClient, METRICS_BATCH_SEND_INTERVAL, config.shouldRetryMetrics); - processor.startProcessing(); + processor.startProcessing(this.globalTags); return processor; } } @@ -202,4 +206,12 @@ export class MetricsListener { } return ""; } + + private getGlobalTags(context?: Context) { + const tags = getEnhancedMetricTags(context); + if (context?.invokedFunctionArn) { + tags.push(`function_arn:${context.invokedFunctionArn}`); + } + return tags; + } } diff --git a/src/metrics/model.ts b/src/metrics/model.ts index b8b824ce..bba5f4b7 100644 --- a/src/metrics/model.ts +++ b/src/metrics/model.ts @@ -19,7 +19,7 @@ export interface MetricKey { } export interface Metric extends MetricKey { - toAPIMetrics(): APIMetric[]; + toAPIMetrics(tags?: string[]): APIMetric[]; /** * Union creates a new metric that is the union of this metric, and another metric. */ @@ -40,12 +40,15 @@ export class Distribution implements Metric { this.tags = tags; } - public toAPIMetrics(): APIMetric[] { + public toAPIMetrics(tags?: string[]): APIMetric[] { const points: APIPoint[] = this.points.map((point) => { // Convert the milliseconds we get from getTime to seconds for the Datadog API const unixSeconds = Math.floor(point.timestamp.getTime() / 1000); return [unixSeconds, [point.value]]; }); + if (tags != undefined) { + this.tags = [...this.tags, ...tags]; + } return [ { metric: this.name, diff --git a/src/metrics/processor.ts b/src/metrics/processor.ts index 5a607130..316dccb1 100644 --- a/src/metrics/processor.ts +++ b/src/metrics/processor.ts @@ -34,12 +34,12 @@ export class Processor { /** * Start processing incoming metrics asynchronously. */ - public startProcessing() { + public startProcessing(tags?: string[]) { if (this.loopPromise !== undefined) { return; } this.timer.start(); - this.loopPromise = this.sendMetricsLoop(); + this.loopPromise = this.sendMetricsLoop(tags); } /** @@ -62,12 +62,12 @@ export class Processor { await this.loopPromise; } - private async sendMetricsLoop() { + private async sendMetricsLoop(tags?: string[]) { while (!(await this.timer.nextTimeout())) { const oldBatcher = this.batcher; this.batcher = new Batcher(); - const metrics = oldBatcher.toAPIMetrics(); + const metrics = oldBatcher.toAPIMetrics(tags); if (metrics.length === 0) { continue; } @@ -81,7 +81,7 @@ export class Processor { } } } - const finalMetrics = this.batcher.toAPIMetrics(); + const finalMetrics = this.batcher.toAPIMetrics(tags); if (finalMetrics.length === 0) { return; } From fb352f4d254bb0c8867891436d393ce4edaa3d6e Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Fri, 28 Jun 2024 10:32:02 -0400 Subject: [PATCH 02/11] warn on timestamp --- src/metrics/listener.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/metrics/listener.ts b/src/metrics/listener.ts index 40f31ebb..0db2759b 100644 --- a/src/metrics/listener.ts +++ b/src/metrics/listener.ts @@ -1,6 +1,6 @@ import { StatsD } from "hot-shots"; import { promisify } from "util"; -import { logDebug, logError } from "../utils"; +import { logDebug, logError, logWarning } from "../utils"; import { flushExtension, isExtensionRunning } from "./extension"; import { KMSService } from "./kms-service"; import { writeMetricToStdout } from "./metric-log"; @@ -142,6 +142,11 @@ export class MetricsListener { if (this.isExtensionRunning) { const isMetricTimeValid = Date.parse(metricTime.toString()) > 0; if (isMetricTimeValid) { + const dateCeiling = new Date(Date.now() - 4 * 60 * 60 * 1000) // 4 hours ago + if (dateCeiling > metricTime) { + logWarning("The timestamp provided is too old to be sent to the Datadog API. Please provide a timestamp within the last 4 hours."); + return; + } // Only create the processor to submit metrics to the API when a user provides a valid timestamp as // Dogstatsd does not support timestamps for distributions. this.currentProcessor = this.createProcessor(this.config, this.apiKey); From 3305e356d662328048d9bf1dbcca423f77e2b52b Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Fri, 28 Jun 2024 11:13:56 -0400 Subject: [PATCH 03/11] make pretty --- src/index.ts | 8 ++++---- src/metrics/batcher.ts | 2 +- src/metrics/listener.ts | 6 ++++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/index.ts b/src/index.ts index fb5525de..5e107006 100644 --- a/src/index.ts +++ b/src/index.ts @@ -421,13 +421,13 @@ function getRuntimeTag(): string { function getDDTags(): string[] { const ddTags = getEnvValue("DD_TAGS", "").split(","); - const ddService = getEnvValue("DD_SERVICE", "") + const ddService = getEnvValue("DD_SERVICE", ""); if (ddService.length > 0) { - ddTags.push(`service:${ddService}`) + ddTags.push(`service:${ddService}`); } - const ddEnv = getEnvValue("DD_ENV", "") + const ddEnv = getEnvValue("DD_ENV", ""); if (ddEnv.length > 0) { - ddTags.push(`env:${ddEnv}`) + ddTags.push(`env:${ddEnv}`); } return ddTags; } diff --git a/src/metrics/batcher.ts b/src/metrics/batcher.ts index bc872679..54b031ee 100644 --- a/src/metrics/batcher.ts +++ b/src/metrics/batcher.ts @@ -23,7 +23,7 @@ export class Batcher { * Convert batched metrics to a list of api compatible metrics */ public toAPIMetrics(tags?: string[]): APIMetric[] { - return [...this.metrics.values()].flatMap((metric) => metric.toAPIMetrics(tags)) + return [...this.metrics.values()].flatMap((metric) => metric.toAPIMetrics(tags)); } private getBatchKey(metric: Metric): string { diff --git a/src/metrics/listener.ts b/src/metrics/listener.ts index 0db2759b..1b912736 100644 --- a/src/metrics/listener.ts +++ b/src/metrics/listener.ts @@ -142,9 +142,11 @@ export class MetricsListener { if (this.isExtensionRunning) { const isMetricTimeValid = Date.parse(metricTime.toString()) > 0; if (isMetricTimeValid) { - const dateCeiling = new Date(Date.now() - 4 * 60 * 60 * 1000) // 4 hours ago + const dateCeiling = new Date(Date.now() - 4 * 60 * 60 * 1000); // 4 hours ago if (dateCeiling > metricTime) { - logWarning("The timestamp provided is too old to be sent to the Datadog API. Please provide a timestamp within the last 4 hours."); + logWarning( + "The timestamp provided is too old to be sent to the Datadog API. Please provide a timestamp within the last 4 hours.", + ); return; } // Only create the processor to submit metrics to the API when a user provides a valid timestamp as From 1c3bee9d6944305f9a0a47cf4c00f8b533239c1f Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Fri, 28 Jun 2024 11:55:58 -0400 Subject: [PATCH 04/11] modify test --- src/metrics/listener.spec.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/metrics/listener.spec.ts b/src/metrics/listener.spec.ts index 244b0197..d80a2890 100644 --- a/src/metrics/listener.spec.ts +++ b/src/metrics/listener.spec.ts @@ -6,6 +6,7 @@ import { EXTENSION_URL } from "./extension"; import { MetricsListener } from "./listener"; import StatsDClient from "hot-shots"; +import { Context } from "aws-lambda"; jest.mock("hot-shots"); const siteURL = "example.com"; @@ -143,7 +144,7 @@ describe("MetricsListener", () => { mock({ "/opt/extensions/datadog-agent": Buffer.from([0]), }); - nock("https://api.example.com").post("/api/v1/distribution_points?api_key=api-key").reply(200, {}); + const apiScope = nock("https://api.example.com").post("/api/v1/distribution_points?api_key=api-key").reply(200, {}); const distributionMock = jest.fn(); (StatsDClient as any).mockImplementation(() => { @@ -153,8 +154,6 @@ describe("MetricsListener", () => { }; }); - jest.spyOn(Date, "now").mockImplementation(() => 1487076708000); - const metricTimeOneMinuteAgo = new Date(Date.now() - 60000); const kms = new MockKMS("kms-api-key-decrypted"); const listener = new MetricsListener(kms as any, { @@ -166,8 +165,12 @@ describe("MetricsListener", () => { localTesting: true, siteURL, }); + const mockARN = "arn:aws:lambda:us-east-1:123497598159:function:my-test-lambda"; + const mockContext = { + invokedFunctionArn: mockARN, + } as any as Context; - await listener.onStartInvocation({}); + await listener.onStartInvocation({}, mockContext); listener.sendDistributionMetricWithDate( "my-metric-with-a-timestamp", 10, @@ -178,8 +181,9 @@ describe("MetricsListener", () => { ); listener.sendDistributionMetric("my-metric-without-a-timestamp", 10, false, "tag:a", "tag:b"); await listener.onCompleteInvocation(); + expect(flushScope.isDone()).toBeTruthy(); - expect(nock.isDone()).toBeTruthy(); + expect(apiScope.isDone()).toBeTruthy(); expect(distributionMock).toHaveBeenCalledWith("my-metric-without-a-timestamp", 10, undefined, ["tag:a", "tag:b"]); }); From 691f8271549f6f492f5141b270770c7063b7da28 Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Fri, 28 Jun 2024 11:58:33 -0400 Subject: [PATCH 05/11] lint --- src/metrics/model.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/metrics/model.ts b/src/metrics/model.ts index bba5f4b7..72ba643a 100644 --- a/src/metrics/model.ts +++ b/src/metrics/model.ts @@ -46,7 +46,7 @@ export class Distribution implements Metric { const unixSeconds = Math.floor(point.timestamp.getTime() / 1000); return [unixSeconds, [point.value]]; }); - if (tags != undefined) { + if (tags !== undefined) { this.tags = [...this.tags, ...tags]; } return [ From 0cb1c1546eeb68d57832425e453c3182579265ea Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Mon, 1 Jul 2024 15:50:30 -0400 Subject: [PATCH 06/11] simplify + fix test --- src/metrics/batcher.ts | 4 ++-- src/metrics/listener.ts | 6 +++++- src/metrics/model.ts | 7 ++----- src/metrics/processor.ts | 10 +++++----- 4 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/metrics/batcher.ts b/src/metrics/batcher.ts index 54b031ee..4da14e82 100644 --- a/src/metrics/batcher.ts +++ b/src/metrics/batcher.ts @@ -22,8 +22,8 @@ export class Batcher { /** * Convert batched metrics to a list of api compatible metrics */ - public toAPIMetrics(tags?: string[]): APIMetric[] { - return [...this.metrics.values()].flatMap((metric) => metric.toAPIMetrics(tags)); + public toAPIMetrics(): APIMetric[] { + return [...this.metrics.values()].flatMap((metric) => metric.toAPIMetrics()); } private getBatchKey(metric: Metric): string { diff --git a/src/metrics/listener.ts b/src/metrics/listener.ts index 1b912736..d95695ea 100644 --- a/src/metrics/listener.ts +++ b/src/metrics/listener.ts @@ -68,7 +68,6 @@ export class MetricsListener { } public async onStartInvocation(_: any, context?: Context) { - this.globalTags = this.getGlobalTags(context); if (this.isExtensionRunning === undefined) { this.isExtensionRunning = await isExtensionRunning(); logDebug(`Extension present: ${this.isExtensionRunning}`); @@ -77,6 +76,7 @@ export class MetricsListener { if (this.isExtensionRunning) { logDebug(`Using StatsD client`); + this.globalTags = this.getGlobalTags(context); this.statsDClient = new StatsD({ host: "127.0.0.1", closingFlushInterval: 1 }); return; } @@ -152,6 +152,10 @@ export class MetricsListener { // Only create the processor to submit metrics to the API when a user provides a valid timestamp as // Dogstatsd does not support timestamps for distributions. this.currentProcessor = this.createProcessor(this.config, this.apiKey); + // Add global tags to metrics sent to the API + if (this.globalTags !== undefined && this.globalTags.length > 0) { + tags = [...tags, ...this.globalTags]; + } } else { this.statsDClient?.distribution(name, value, undefined, tags); return; diff --git a/src/metrics/model.ts b/src/metrics/model.ts index 72ba643a..b8b824ce 100644 --- a/src/metrics/model.ts +++ b/src/metrics/model.ts @@ -19,7 +19,7 @@ export interface MetricKey { } export interface Metric extends MetricKey { - toAPIMetrics(tags?: string[]): APIMetric[]; + toAPIMetrics(): APIMetric[]; /** * Union creates a new metric that is the union of this metric, and another metric. */ @@ -40,15 +40,12 @@ export class Distribution implements Metric { this.tags = tags; } - public toAPIMetrics(tags?: string[]): APIMetric[] { + public toAPIMetrics(): APIMetric[] { const points: APIPoint[] = this.points.map((point) => { // Convert the milliseconds we get from getTime to seconds for the Datadog API const unixSeconds = Math.floor(point.timestamp.getTime() / 1000); return [unixSeconds, [point.value]]; }); - if (tags !== undefined) { - this.tags = [...this.tags, ...tags]; - } return [ { metric: this.name, diff --git a/src/metrics/processor.ts b/src/metrics/processor.ts index 316dccb1..5a607130 100644 --- a/src/metrics/processor.ts +++ b/src/metrics/processor.ts @@ -34,12 +34,12 @@ export class Processor { /** * Start processing incoming metrics asynchronously. */ - public startProcessing(tags?: string[]) { + public startProcessing() { if (this.loopPromise !== undefined) { return; } this.timer.start(); - this.loopPromise = this.sendMetricsLoop(tags); + this.loopPromise = this.sendMetricsLoop(); } /** @@ -62,12 +62,12 @@ export class Processor { await this.loopPromise; } - private async sendMetricsLoop(tags?: string[]) { + private async sendMetricsLoop() { while (!(await this.timer.nextTimeout())) { const oldBatcher = this.batcher; this.batcher = new Batcher(); - const metrics = oldBatcher.toAPIMetrics(tags); + const metrics = oldBatcher.toAPIMetrics(); if (metrics.length === 0) { continue; } @@ -81,7 +81,7 @@ export class Processor { } } } - const finalMetrics = this.batcher.toAPIMetrics(tags); + const finalMetrics = this.batcher.toAPIMetrics(); if (finalMetrics.length === 0) { return; } From c335ae5cccb9c080a419c5cd982d9205d87885e5 Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Wed, 3 Jul 2024 13:45:27 -0400 Subject: [PATCH 07/11] improve log message + add test --- src/metrics/listener.spec.ts | 25 +++++++++++++++++++++++++ src/metrics/listener.ts | 4 +--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/metrics/listener.spec.ts b/src/metrics/listener.spec.ts index d80a2890..abf6771f 100644 --- a/src/metrics/listener.spec.ts +++ b/src/metrics/listener.spec.ts @@ -187,6 +187,31 @@ describe("MetricsListener", () => { expect(distributionMock).toHaveBeenCalledWith("my-metric-without-a-timestamp", 10, undefined, ["tag:a", "tag:b"]); }); + it("does not send historical metrics from over 4 hours ago to the API", async () => { + mock({ + "/opt/extensions/datadog-agent": Buffer.from([0]), + }); + const apiScope = nock("https://api.example.com").post("/api/v1/distribution_points?api_key=api-key").reply(200, {}); + + const metricTimeFiveHoursAgo = new Date(Date.now() - 5 * 60 * 60 * 1000); // 5 hours ago + const kms = new MockKMS("kms-api-key-decrypted"); + const listener = new MetricsListener(kms as any, { + apiKey: "api-key", + apiKeyKMS: "", + enhancedMetrics: false, + logForwarding: false, + shouldRetryMetrics: false, + localTesting: true, + siteURL, + }); + + await listener.onStartInvocation({}); + listener.sendDistributionMetricWithDate("my-metric-with-a-timestamp", 10, metricTimeFiveHoursAgo, false); + await listener.onCompleteInvocation(); + + expect(apiScope.isDone()).toBeFalsy(); + }); + it("logs metrics when logForwarding is enabled with custom timestamp", async () => { const spy = jest.spyOn(process.stdout, "write"); // jest.spyOn(Date, "now").mockImplementation(() => 1487076708000); diff --git a/src/metrics/listener.ts b/src/metrics/listener.ts index d95695ea..3bfbe9d9 100644 --- a/src/metrics/listener.ts +++ b/src/metrics/listener.ts @@ -144,9 +144,7 @@ export class MetricsListener { if (isMetricTimeValid) { const dateCeiling = new Date(Date.now() - 4 * 60 * 60 * 1000); // 4 hours ago if (dateCeiling > metricTime) { - logWarning( - "The timestamp provided is too old to be sent to the Datadog API. Please provide a timestamp within the last 4 hours.", - ); + logWarning(`Timestamp ${metricTime.toISOString()} is older than 4 hours, not submitting metric ${name}`); return; } // Only create the processor to submit metrics to the API when a user provides a valid timestamp as From 6aa4ba36f09a6d674cf6fdaa327b7af2f83eed28 Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Wed, 3 Jul 2024 14:03:54 -0400 Subject: [PATCH 08/11] add test for tags --- src/index.spec.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/index.spec.ts b/src/index.spec.ts index a11868d6..50109b95 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -555,6 +555,18 @@ describe("sendDistributionMetricWithDate", () => { sendDistributionMetricWithDate("metric", 1, new Date(), "first-tag", "second-tag"); expect(_metricsQueue.length).toBe(1); }); + it("attaches tags from Datadog environment variables to the metric", () => { + process.env.DD_TAGS = "env:testing,env:prod"; + sendDistributionMetricWithDate("metric", 1, new Date(Date.now() - 1 * 60 * 60 * 1000), "first-tag", "second-tag"); + expect(_metricsQueue.length).toBe(1); + expect(_metricsQueue.pop()?.tags).toEqual([ + "first-tag", + "second-tag", + `dd_lambda_layer:datadog-node${process.version}`, + "env:testing", + "env:prod", + ]); + }); }); describe("emitTelemetryOnErrorOutsideHandler", () => { From c8d9a781f149d51bda6cd152065dbf4aa7128c30 Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Wed, 3 Jul 2024 14:19:23 -0400 Subject: [PATCH 09/11] fix test --- src/index.spec.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/index.spec.ts b/src/index.spec.ts index 50109b95..eba64684 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -556,16 +556,16 @@ describe("sendDistributionMetricWithDate", () => { expect(_metricsQueue.length).toBe(1); }); it("attaches tags from Datadog environment variables to the metric", () => { - process.env.DD_TAGS = "env:testing,env:prod"; + process.env.DD_TAGS = "foo:bar,hello:world"; sendDistributionMetricWithDate("metric", 1, new Date(Date.now() - 1 * 60 * 60 * 1000), "first-tag", "second-tag"); expect(_metricsQueue.length).toBe(1); - expect(_metricsQueue.pop()?.tags).toEqual([ - "first-tag", - "second-tag", - `dd_lambda_layer:datadog-node${process.version}`, - "env:testing", - "env:prod", - ]); + const metricTags = _metricsQueue.pop()?.tags; + expect(metricTags).toBeDefined(); + ["first-tag", "second-tag", `dd_lambda_layer:datadog-node${process.version}`, "foo:bar", "hello:world"].forEach( + (tag) => { + expect(metricTags?.indexOf(tag)).toBeGreaterThanOrEqual(0); + }, + ); }); }); From 914893d89965ed408343cf2302e072e132357ae6 Mon Sep 17 00:00:00 2001 From: Dylan Yang Date: Mon, 8 Jul 2024 16:35:49 -0400 Subject: [PATCH 10/11] handle arn tag alias --- src/metrics/listener.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/metrics/listener.ts b/src/metrics/listener.ts index 3bfbe9d9..8fbafd25 100644 --- a/src/metrics/listener.ts +++ b/src/metrics/listener.ts @@ -219,7 +219,13 @@ export class MetricsListener { private getGlobalTags(context?: Context) { const tags = getEnhancedMetricTags(context); if (context?.invokedFunctionArn) { - tags.push(`function_arn:${context.invokedFunctionArn}`); + const splitArn = context.invokedFunctionArn.split(":"); + if (splitArn.length > 7) { + // Get rid of the alias + splitArn.pop(); + } + const arn = splitArn.join(":"); + tags.push(`function_arn:${arn}`); } return tags; } From 167d38c39b1bcdeb769285b357b0c57a9fd999b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?jordan=20gonz=C3=A1lez?= <30836115+duncanista@users.noreply.github.com> Date: Tue, 16 Jul 2024 12:50:49 -0400 Subject: [PATCH 11/11] convert number into constant --- src/metrics/listener.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/metrics/listener.ts b/src/metrics/listener.ts index 8fbafd25..4a50aecd 100644 --- a/src/metrics/listener.ts +++ b/src/metrics/listener.ts @@ -9,6 +9,7 @@ import { Context } from "aws-lambda"; import { getEnhancedMetricTags } from "./enhanced-metrics"; const METRICS_BATCH_SEND_INTERVAL = 10000; // 10 seconds +const HISTORICAL_METRICS_THRESHOLD_HOURS = 4 * 60 * 60 * 1000; // 4 hours export interface MetricsConfig { /** @@ -142,7 +143,7 @@ export class MetricsListener { if (this.isExtensionRunning) { const isMetricTimeValid = Date.parse(metricTime.toString()) > 0; if (isMetricTimeValid) { - const dateCeiling = new Date(Date.now() - 4 * 60 * 60 * 1000); // 4 hours ago + const dateCeiling = new Date(Date.now() - HISTORICAL_METRICS_THRESHOLD_HOURS); // 4 hours ago if (dateCeiling > metricTime) { logWarning(`Timestamp ${metricTime.toISOString()} is older than 4 hours, not submitting metric ${name}`); return;