From aa2b85ee18ce57a5ff777a49143f05d34ee17a5c Mon Sep 17 00:00:00 2001 From: nagydaoudt Date: Thu, 29 Feb 2024 12:17:05 +0100 Subject: [PATCH 1/5] #491: adding compression to metrics API --- src/index.ts | 1 + src/metrics/api.spec.ts | 40 +++++++++++++++++++++++++++++++++--- src/metrics/api.ts | 4 ++-- src/metrics/listener.spec.ts | 7 ++++++- src/metrics/listener.ts | 8 +++++++- src/utils/request.ts | 14 +++++++++++-- 6 files changed, 65 insertions(+), 9 deletions(-) diff --git a/src/index.ts b/src/index.ts index 4b5e98df..cb3144d8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -88,6 +88,7 @@ export const defaultConfig: Config = { minColdStartTraceDuration: 3, coldStartTraceSkipLib: "", localTesting: false, + compressPayload: false } as const; let currentMetricsListener: MetricsListener | undefined; diff --git a/src/metrics/api.spec.ts b/src/metrics/api.spec.ts index 72e7c0e8..b569b0e6 100644 --- a/src/metrics/api.spec.ts +++ b/src/metrics/api.spec.ts @@ -2,6 +2,7 @@ import nock from "nock"; import { APIClient } from "./api"; import { APIMetric } from "./model"; +import { deflateSync } from "zlib"; const baseAPIURL = "https://www.example.com/"; @@ -33,7 +34,40 @@ describe("APIClient", () => { const scope = nock(baseAPIURL) .post("/api/v1/distribution_points?api_key=api_key", JSON.stringify({ series: input })) .reply(200); - const client = new APIClient("api_key", baseAPIURL); + const client = new APIClient("api_key", baseAPIURL, false); + + await client.sendMetrics(input); + expect(scope.isDone()).toBeTruthy(); + }); + + it("sends metrics with compression", async () => { + const input: APIMetric[] = [ + { + metric: "a-metric", + points: [ + [1, [2]], + [3, [4]], + [5, [6]], + ], + tags: ["a", "b", "c"], + type: "distribution", + }, + { + metric: "b-metric", + points: [ + [1, [2]], + [3, [4]], + [5, [6]], + ], + tags: ["a", "b", "c"], + type: "distribution", + }, + ]; + + const scope = nock(baseAPIURL) + .post("/api/v1/distribution_points?api_key=api_key", deflateSync(JSON.stringify({ series: input })), { reqheaders: { "content-encoding": "deflate" } }) + .reply(200); + const client = new APIClient("api_key", baseAPIURL, true); await client.sendMetrics(input); expect(scope.isDone()).toBeTruthy(); @@ -43,7 +77,7 @@ describe("APIClient", () => { const scope = nock(baseAPIURL) .post("/api/v1/distribution_points?api_key=bad_api_key", JSON.stringify({ series: [] })) .reply(403); - const client = new APIClient("bad_api_key", baseAPIURL); + const client = new APIClient("bad_api_key", baseAPIURL, false); await expect(client.sendMetrics([])).rejects.toMatchInlineSnapshot(`"HTTP error code: 403"`); expect(scope.isDone()).toBeTruthy(); }); @@ -52,7 +86,7 @@ describe("APIClient", () => { const scope = nock(baseAPIURL) .post("/api/v1/distribution_points?api_key=api_key", JSON.stringify({ series: [] })) .replyWithError("Connection closed"); - const client = new APIClient("api_key", baseAPIURL); + const client = new APIClient("api_key", baseAPIURL, false); await expect(client.sendMetrics([])).rejects.toMatchInlineSnapshot(`"Connection closed"`); expect(scope.isDone()).toBeTruthy(); }); diff --git a/src/metrics/api.ts b/src/metrics/api.ts index 446d2e91..f0704c51 100644 --- a/src/metrics/api.ts +++ b/src/metrics/api.ts @@ -15,10 +15,10 @@ export interface Client { * APIClient interfaces with the Datadog API */ export class APIClient implements Client { - constructor(private apiKey: string, private baseAPIURL: string) {} + constructor(private apiKey: string, private baseAPIURL: string, private compressPayload: boolean) {} public async sendMetrics(metrics: APIMetric[]): Promise { - const result = await post(this.getUrl("api/v1/distribution_points"), { series: metrics }); + const result = await post(this.getUrl("api/v1/distribution_points"), { series: metrics }, {}, this.compressPayload); if (result.success) { return; } diff --git a/src/metrics/listener.spec.ts b/src/metrics/listener.spec.ts index 245d2176..e8caedad 100644 --- a/src/metrics/listener.spec.ts +++ b/src/metrics/listener.spec.ts @@ -1,4 +1,3 @@ -import { AWSError, KMS, Request } from "aws-sdk"; import nock from "nock"; import mock from "mock-fs"; @@ -38,6 +37,7 @@ describe("MetricsListener", () => { logForwarding: false, shouldRetryMetrics: false, localTesting: false, + compressPayload: false, siteURL, }); @@ -58,6 +58,7 @@ describe("MetricsListener", () => { logForwarding: false, shouldRetryMetrics: false, localTesting: false, + compressPayload: false, siteURL, }); @@ -76,6 +77,7 @@ describe("MetricsListener", () => { logForwarding: false, shouldRetryMetrics: false, localTesting: false, + compressPayload: false, siteURL, }); @@ -95,6 +97,7 @@ describe("MetricsListener", () => { logForwarding: true, shouldRetryMetrics: false, localTesting: false, + compressPayload: false, siteURL, }); jest.useFakeTimers("legacy"); @@ -129,6 +132,7 @@ describe("MetricsListener", () => { logForwarding: true, shouldRetryMetrics: false, localTesting: true, + compressPayload: false, siteURL, }); jest.useFakeTimers("legacy"); @@ -152,6 +156,7 @@ describe("MetricsListener", () => { logForwarding: true, shouldRetryMetrics: false, localTesting: false, + compressPayload: false, siteURL, }); // jest.useFakeTimers(); diff --git a/src/metrics/listener.ts b/src/metrics/listener.ts index 076e7b3e..fb3aea20 100644 --- a/src/metrics/listener.ts +++ b/src/metrics/listener.ts @@ -53,6 +53,12 @@ export interface MetricsConfig { * from the runtime */ localTesting: boolean; + + /** + * If set, Compresses requests payload in the metrics request using zlib + * @default false + */ + compressPayload: boolean; } export class MetricsListener { @@ -173,7 +179,7 @@ export class MetricsListener { private async createProcessor(config: MetricsConfig, apiKey: Promise) { const key = await apiKey; const url = `https://api.${config.siteURL}`; - const apiClient = new APIClient(key, url); + const apiClient = new APIClient(key, url, config.compressPayload); const processor = new Processor(apiClient, metricsBatchSendIntervalMS, config.shouldRetryMetrics); processor.startProcessing(); return processor; diff --git a/src/utils/request.ts b/src/utils/request.ts index ded6f94f..412fdb17 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -2,6 +2,7 @@ import https, { RequestOptions } from "https"; import http from "http"; import { URL } from "url"; import { logDebug } from "./log"; +import { deflateSync } from "zlib"; type RequestResult = { success: boolean; @@ -9,9 +10,18 @@ type RequestResult = { errorMessage?: string; }; -export function post(url: URL, body: T, options?: Partial): Promise { +export function post(url: URL, body: T, options?: Partial, compressPayload?: boolean): Promise { const bodyJSON = JSON.stringify(body); - const buffer = Buffer.from(bodyJSON); + let buffer = Buffer.from(bodyJSON); + + if (compressPayload) { + // Adding compression header + options = options || {}; // Define options object if not already defined + options.headers = { ...options.headers, "Content-Encoding": "deflate" }; + + buffer = deflateSync(buffer); + } + logDebug(`sending payload with body ${bodyJSON}`); const requestOptions: RequestOptions = { headers: { "content-type": "application/json" }, From 875fe03d8ba6807ac51ee9cb92128c44decf29ec Mon Sep 17 00:00:00 2001 From: nagydaoudt Date: Thu, 29 Feb 2024 13:18:20 +0100 Subject: [PATCH 2/5] Compressing by default --- README.md | 1 + src/index.spec.ts | 9 +++++---- src/index.ts | 8 +++++++- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 80a7b70f..cbc87d7b 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ Besides the environment variables supported by dd-trace-js, the datadog-lambda-j | DD_COLD_START_TRACE_SKIP_LIB | optionally skip creating Cold Start Spans for a comma-separated list of libraries. Useful to limit depth or skip known libraries. | `./opentracing/tracer` | | DD_CAPTURE_LAMBDA_PAYLOAD | [Captures incoming and outgoing AWS Lambda payloads][1] in the Datadog APM spans for Lambda invocations. | `false` | | DD_CAPTURE_LAMBDA_PAYLOAD_MAX_DEPTH | Determines the level of detail captured from AWS Lambda payloads, which are then assigned as tags for the `aws.lambda` span. It specifies the nesting depth of the JSON payload structure to process. Once the specified maximum depth is reached, the tag's value is set to the stringified value of any nested elements beyond this level.
For example, given the input payload:
{
"lv1" : {
"lv2": {
"lv3": "val"
}
}
}
If the depth is set to `2`, the resulting tag's key is set to `function.request.lv1.lv2` and the value is `{\"lv3\": \"val\"}`.
If the depth is set to `0`, the resulting tag's key is set to `function.request` and value is `{\"lv1\":{\"lv2\":{\"lv3\": \"val\"}}}` | `10` | +| DD_COMPRESS_METRIC_PAYLOAD | Compresses metrics requests payload | `true` | ## Lambda Profiling Beta diff --git a/src/index.spec.ts b/src/index.spec.ts index 17f226e2..52fb259b 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -10,6 +10,7 @@ import { PassThrough } from "stream"; import { DatadogTraceHeaders } from "./trace/context/extractor"; import { SpanContextWrapper } from "./trace/span-context-wrapper"; import { TraceSource } from "./trace/trace-context-service"; +import { inflateSync } from "zlib"; jest.mock("./metrics/enhanced-metrics"); @@ -141,7 +142,7 @@ describe("datadog", () => { process.env[apiKeyVar] = apiKey; nock("https://api.datadoghq.com/") - .post(`/api/v1/distribution_points?api_key=${apiKey}`, (request: any) => request.series[0].metric === "my-dist") + .post(`/api/v1/distribution_points?api_key=${apiKey}`, (request: any) => JSON.parse(inflateSync(Buffer.from(request, 'hex')).toString()).series[0].metric === "my-dist") .reply(200, {}); const wrapped = datadog( @@ -163,7 +164,7 @@ describe("datadog", () => { const apiKey = "101112"; nock("https://api.datadoghq.com/") - .post(`/api/v1/distribution_points?api_key=${apiKey}`, (request: any) => request.series[0].metric === "my-dist") + .post(`/api/v1/distribution_points?api_key=${apiKey}`, (request: any) => JSON.parse(inflateSync(Buffer.from(request, 'hex')).toString()).series[0].metric === "my-dist") .reply(200, {}); const wrapped = datadog( @@ -185,7 +186,7 @@ describe("datadog", () => { process.env[siteEnvVar] = site; nock("https://api.datadoghq.com/") - .post(`/api/v1/distribution_points?api_key=${apiKey}`, (request: any) => request.series[0].metric === "my-dist") + .post(`/api/v1/distribution_points?api_key=${apiKey}`, (request: any) => JSON.parse(inflateSync(Buffer.from(request, 'hex')).toString()).series[0].metric === "my-dist") .reply(200, {}); const wrapped = datadog( @@ -207,7 +208,7 @@ describe("datadog", () => { process.env[siteEnvVar] = site; nock("https://api.datadoghq.com/") - .post(`/api/v1/distribution_points?api_key=${apiKey}`, (request: any) => request.series[0].metric === "my-dist") + .post(`/api/v1/distribution_points?api_key=${apiKey}`, (request: any) => JSON.parse(inflateSync(Buffer.from(request, 'hex')).toString()).series[0].metric === "my-dist") .reply(200, {}); const wrapped = datadog( diff --git a/src/index.ts b/src/index.ts index cb3144d8..ab0b9e81 100644 --- a/src/index.ts +++ b/src/index.ts @@ -45,6 +45,7 @@ export const coldStartTracingEnvVar = "DD_COLD_START_TRACING"; export const minColdStartTraceDurationEnvVar = "DD_MIN_COLD_START_DURATION"; export const coldStartTraceSkipLibEnvVar = "DD_COLD_START_TRACE_SKIP_LIB"; export const localTestingEnvVar = "DD_LOCAL_TESTING"; +export const compressPayloadEnvVar = "DD_COMPRESS_METRIC_PAYLOAD"; interface GlobalConfig { /** @@ -88,7 +89,7 @@ export const defaultConfig: Config = { minColdStartTraceDuration: 3, coldStartTraceSkipLib: "", localTesting: false, - compressPayload: false + compressPayload: true } as const; let currentMetricsListener: MetricsListener | undefined; @@ -356,6 +357,11 @@ function getConfig(userConfig?: Partial): Config { config.decodeAuthorizerContext = result === "true"; } + if (userConfig === undefined || userConfig.compressPayload === undefined) { + const result = getEnvValue(compressPayloadEnvVar, "true").toLowerCase(); + config.compressPayload = result === "true"; + } + if (userConfig === undefined || userConfig.minColdStartTraceDuration === undefined) { config.minColdStartTraceDuration = Number(getEnvValue(minColdStartTraceDurationEnvVar, "3")); } From f8912fc88a7011ecee4897774731dc50a9090b16 Mon Sep 17 00:00:00 2001 From: nagydaoudt Date: Thu, 29 Feb 2024 14:58:54 +0100 Subject: [PATCH 3/5] removing DD_COMPRESS_METRIC_PAYLOAD env var --- README.md | 1 - src/index.ts | 6 ------ 2 files changed, 7 deletions(-) diff --git a/README.md b/README.md index cbc87d7b..80a7b70f 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,6 @@ Besides the environment variables supported by dd-trace-js, the datadog-lambda-j | DD_COLD_START_TRACE_SKIP_LIB | optionally skip creating Cold Start Spans for a comma-separated list of libraries. Useful to limit depth or skip known libraries. | `./opentracing/tracer` | | DD_CAPTURE_LAMBDA_PAYLOAD | [Captures incoming and outgoing AWS Lambda payloads][1] in the Datadog APM spans for Lambda invocations. | `false` | | DD_CAPTURE_LAMBDA_PAYLOAD_MAX_DEPTH | Determines the level of detail captured from AWS Lambda payloads, which are then assigned as tags for the `aws.lambda` span. It specifies the nesting depth of the JSON payload structure to process. Once the specified maximum depth is reached, the tag's value is set to the stringified value of any nested elements beyond this level.
For example, given the input payload:
{
"lv1" : {
"lv2": {
"lv3": "val"
}
}
}
If the depth is set to `2`, the resulting tag's key is set to `function.request.lv1.lv2` and the value is `{\"lv3\": \"val\"}`.
If the depth is set to `0`, the resulting tag's key is set to `function.request` and value is `{\"lv1\":{\"lv2\":{\"lv3\": \"val\"}}}` | `10` | -| DD_COMPRESS_METRIC_PAYLOAD | Compresses metrics requests payload | `true` | ## Lambda Profiling Beta diff --git a/src/index.ts b/src/index.ts index ab0b9e81..0f12b7e2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -45,7 +45,6 @@ export const coldStartTracingEnvVar = "DD_COLD_START_TRACING"; export const minColdStartTraceDurationEnvVar = "DD_MIN_COLD_START_DURATION"; export const coldStartTraceSkipLibEnvVar = "DD_COLD_START_TRACE_SKIP_LIB"; export const localTestingEnvVar = "DD_LOCAL_TESTING"; -export const compressPayloadEnvVar = "DD_COMPRESS_METRIC_PAYLOAD"; interface GlobalConfig { /** @@ -357,11 +356,6 @@ function getConfig(userConfig?: Partial): Config { config.decodeAuthorizerContext = result === "true"; } - if (userConfig === undefined || userConfig.compressPayload === undefined) { - const result = getEnvValue(compressPayloadEnvVar, "true").toLowerCase(); - config.compressPayload = result === "true"; - } - if (userConfig === undefined || userConfig.minColdStartTraceDuration === undefined) { config.minColdStartTraceDuration = Number(getEnvValue(minColdStartTraceDurationEnvVar, "3")); } From 516f969c178cde4274dd35bad05700c105743627 Mon Sep 17 00:00:00 2001 From: nagydaoudt Date: Thu, 29 Feb 2024 15:06:19 +0100 Subject: [PATCH 4/5] removing compression boolean from configuration --- src/index.ts | 1 - src/metrics/api.spec.ts | 43 +++++------------------------------- src/metrics/api.ts | 4 ++-- src/metrics/listener.spec.ts | 6 ----- src/metrics/listener.ts | 8 +------ 5 files changed, 8 insertions(+), 54 deletions(-) diff --git a/src/index.ts b/src/index.ts index 0f12b7e2..4b5e98df 100644 --- a/src/index.ts +++ b/src/index.ts @@ -88,7 +88,6 @@ export const defaultConfig: Config = { minColdStartTraceDuration: 3, coldStartTraceSkipLib: "", localTesting: false, - compressPayload: true } as const; let currentMetricsListener: MetricsListener | undefined; diff --git a/src/metrics/api.spec.ts b/src/metrics/api.spec.ts index b569b0e6..47916ab3 100644 --- a/src/metrics/api.spec.ts +++ b/src/metrics/api.spec.ts @@ -31,43 +31,10 @@ describe("APIClient", () => { }, ]; - const scope = nock(baseAPIURL) - .post("/api/v1/distribution_points?api_key=api_key", JSON.stringify({ series: input })) - .reply(200); - const client = new APIClient("api_key", baseAPIURL, false); - - await client.sendMetrics(input); - expect(scope.isDone()).toBeTruthy(); - }); - - it("sends metrics with compression", async () => { - const input: APIMetric[] = [ - { - metric: "a-metric", - points: [ - [1, [2]], - [3, [4]], - [5, [6]], - ], - tags: ["a", "b", "c"], - type: "distribution", - }, - { - metric: "b-metric", - points: [ - [1, [2]], - [3, [4]], - [5, [6]], - ], - tags: ["a", "b", "c"], - type: "distribution", - }, - ]; - const scope = nock(baseAPIURL) .post("/api/v1/distribution_points?api_key=api_key", deflateSync(JSON.stringify({ series: input })), { reqheaders: { "content-encoding": "deflate" } }) .reply(200); - const client = new APIClient("api_key", baseAPIURL, true); + const client = new APIClient("api_key", baseAPIURL); await client.sendMetrics(input); expect(scope.isDone()).toBeTruthy(); @@ -75,18 +42,18 @@ describe("APIClient", () => { it("throws an authentication error on authentication failure", async () => { const scope = nock(baseAPIURL) - .post("/api/v1/distribution_points?api_key=bad_api_key", JSON.stringify({ series: [] })) + .post("/api/v1/distribution_points?api_key=bad_api_key", deflateSync(JSON.stringify({ series: [] })), { reqheaders: { "content-encoding": "deflate" } }) .reply(403); - const client = new APIClient("bad_api_key", baseAPIURL, false); + const client = new APIClient("bad_api_key", baseAPIURL); await expect(client.sendMetrics([])).rejects.toMatchInlineSnapshot(`"HTTP error code: 403"`); expect(scope.isDone()).toBeTruthy(); }); it("throws an error on connection error failure", async () => { const scope = nock(baseAPIURL) - .post("/api/v1/distribution_points?api_key=api_key", JSON.stringify({ series: [] })) + .post("/api/v1/distribution_points?api_key=api_key", deflateSync(JSON.stringify({ series: [] })), { reqheaders: { "content-encoding": "deflate" } }) .replyWithError("Connection closed"); - const client = new APIClient("api_key", baseAPIURL, false); + const client = new APIClient("api_key", baseAPIURL); await expect(client.sendMetrics([])).rejects.toMatchInlineSnapshot(`"Connection closed"`); expect(scope.isDone()).toBeTruthy(); }); diff --git a/src/metrics/api.ts b/src/metrics/api.ts index f0704c51..f820dfc5 100644 --- a/src/metrics/api.ts +++ b/src/metrics/api.ts @@ -15,10 +15,10 @@ export interface Client { * APIClient interfaces with the Datadog API */ export class APIClient implements Client { - constructor(private apiKey: string, private baseAPIURL: string, private compressPayload: boolean) {} + constructor(private apiKey: string, private baseAPIURL: string) {} public async sendMetrics(metrics: APIMetric[]): Promise { - const result = await post(this.getUrl("api/v1/distribution_points"), { series: metrics }, {}, this.compressPayload); + const result = await post(this.getUrl("api/v1/distribution_points"), { series: metrics }, {}, true); if (result.success) { return; } diff --git a/src/metrics/listener.spec.ts b/src/metrics/listener.spec.ts index e8caedad..24a57f84 100644 --- a/src/metrics/listener.spec.ts +++ b/src/metrics/listener.spec.ts @@ -37,7 +37,6 @@ describe("MetricsListener", () => { logForwarding: false, shouldRetryMetrics: false, localTesting: false, - compressPayload: false, siteURL, }); @@ -58,7 +57,6 @@ describe("MetricsListener", () => { logForwarding: false, shouldRetryMetrics: false, localTesting: false, - compressPayload: false, siteURL, }); @@ -77,7 +75,6 @@ describe("MetricsListener", () => { logForwarding: false, shouldRetryMetrics: false, localTesting: false, - compressPayload: false, siteURL, }); @@ -97,7 +94,6 @@ describe("MetricsListener", () => { logForwarding: true, shouldRetryMetrics: false, localTesting: false, - compressPayload: false, siteURL, }); jest.useFakeTimers("legacy"); @@ -132,7 +128,6 @@ describe("MetricsListener", () => { logForwarding: true, shouldRetryMetrics: false, localTesting: true, - compressPayload: false, siteURL, }); jest.useFakeTimers("legacy"); @@ -156,7 +151,6 @@ describe("MetricsListener", () => { logForwarding: true, shouldRetryMetrics: false, localTesting: false, - compressPayload: false, siteURL, }); // jest.useFakeTimers(); diff --git a/src/metrics/listener.ts b/src/metrics/listener.ts index fb3aea20..076e7b3e 100644 --- a/src/metrics/listener.ts +++ b/src/metrics/listener.ts @@ -53,12 +53,6 @@ export interface MetricsConfig { * from the runtime */ localTesting: boolean; - - /** - * If set, Compresses requests payload in the metrics request using zlib - * @default false - */ - compressPayload: boolean; } export class MetricsListener { @@ -179,7 +173,7 @@ export class MetricsListener { private async createProcessor(config: MetricsConfig, apiKey: Promise) { const key = await apiKey; const url = `https://api.${config.siteURL}`; - const apiClient = new APIClient(key, url, config.compressPayload); + const apiClient = new APIClient(key, url); const processor = new Processor(apiClient, metricsBatchSendIntervalMS, config.shouldRetryMetrics); processor.startProcessing(); return processor; From a82bb45bad103177785a259e7019fa20287619fa Mon Sep 17 00:00:00 2001 From: nagydaoudt Date: Thu, 29 Feb 2024 15:12:22 +0100 Subject: [PATCH 5/5] linting --- src/index.spec.ts | 24 ++++++++++++++++++++---- src/metrics/api.spec.ts | 12 +++++++++--- src/utils/request.ts | 7 ++++++- 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/index.spec.ts b/src/index.spec.ts index 52fb259b..87ba4280 100644 --- a/src/index.spec.ts +++ b/src/index.spec.ts @@ -142,7 +142,11 @@ describe("datadog", () => { process.env[apiKeyVar] = apiKey; nock("https://api.datadoghq.com/") - .post(`/api/v1/distribution_points?api_key=${apiKey}`, (request: any) => JSON.parse(inflateSync(Buffer.from(request, 'hex')).toString()).series[0].metric === "my-dist") + .post( + `/api/v1/distribution_points?api_key=${apiKey}`, + (request: any) => + JSON.parse(inflateSync(Buffer.from(request, "hex")).toString()).series[0].metric === "my-dist", + ) .reply(200, {}); const wrapped = datadog( @@ -164,7 +168,11 @@ describe("datadog", () => { const apiKey = "101112"; nock("https://api.datadoghq.com/") - .post(`/api/v1/distribution_points?api_key=${apiKey}`, (request: any) => JSON.parse(inflateSync(Buffer.from(request, 'hex')).toString()).series[0].metric === "my-dist") + .post( + `/api/v1/distribution_points?api_key=${apiKey}`, + (request: any) => + JSON.parse(inflateSync(Buffer.from(request, "hex")).toString()).series[0].metric === "my-dist", + ) .reply(200, {}); const wrapped = datadog( @@ -186,7 +194,11 @@ describe("datadog", () => { process.env[siteEnvVar] = site; nock("https://api.datadoghq.com/") - .post(`/api/v1/distribution_points?api_key=${apiKey}`, (request: any) => JSON.parse(inflateSync(Buffer.from(request, 'hex')).toString()).series[0].metric === "my-dist") + .post( + `/api/v1/distribution_points?api_key=${apiKey}`, + (request: any) => + JSON.parse(inflateSync(Buffer.from(request, "hex")).toString()).series[0].metric === "my-dist", + ) .reply(200, {}); const wrapped = datadog( @@ -208,7 +220,11 @@ describe("datadog", () => { process.env[siteEnvVar] = site; nock("https://api.datadoghq.com/") - .post(`/api/v1/distribution_points?api_key=${apiKey}`, (request: any) => JSON.parse(inflateSync(Buffer.from(request, 'hex')).toString()).series[0].metric === "my-dist") + .post( + `/api/v1/distribution_points?api_key=${apiKey}`, + (request: any) => + JSON.parse(inflateSync(Buffer.from(request, "hex")).toString()).series[0].metric === "my-dist", + ) .reply(200, {}); const wrapped = datadog( diff --git a/src/metrics/api.spec.ts b/src/metrics/api.spec.ts index 47916ab3..bd924d68 100644 --- a/src/metrics/api.spec.ts +++ b/src/metrics/api.spec.ts @@ -32,7 +32,9 @@ describe("APIClient", () => { ]; const scope = nock(baseAPIURL) - .post("/api/v1/distribution_points?api_key=api_key", deflateSync(JSON.stringify({ series: input })), { reqheaders: { "content-encoding": "deflate" } }) + .post("/api/v1/distribution_points?api_key=api_key", deflateSync(JSON.stringify({ series: input })), { + reqheaders: { "content-encoding": "deflate" }, + }) .reply(200); const client = new APIClient("api_key", baseAPIURL); @@ -42,7 +44,9 @@ describe("APIClient", () => { it("throws an authentication error on authentication failure", async () => { const scope = nock(baseAPIURL) - .post("/api/v1/distribution_points?api_key=bad_api_key", deflateSync(JSON.stringify({ series: [] })), { reqheaders: { "content-encoding": "deflate" } }) + .post("/api/v1/distribution_points?api_key=bad_api_key", deflateSync(JSON.stringify({ series: [] })), { + reqheaders: { "content-encoding": "deflate" }, + }) .reply(403); const client = new APIClient("bad_api_key", baseAPIURL); await expect(client.sendMetrics([])).rejects.toMatchInlineSnapshot(`"HTTP error code: 403"`); @@ -51,7 +55,9 @@ describe("APIClient", () => { it("throws an error on connection error failure", async () => { const scope = nock(baseAPIURL) - .post("/api/v1/distribution_points?api_key=api_key", deflateSync(JSON.stringify({ series: [] })), { reqheaders: { "content-encoding": "deflate" } }) + .post("/api/v1/distribution_points?api_key=api_key", deflateSync(JSON.stringify({ series: [] })), { + reqheaders: { "content-encoding": "deflate" }, + }) .replyWithError("Connection closed"); const client = new APIClient("api_key", baseAPIURL); await expect(client.sendMetrics([])).rejects.toMatchInlineSnapshot(`"Connection closed"`); diff --git a/src/utils/request.ts b/src/utils/request.ts index 412fdb17..67dc70cf 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -10,7 +10,12 @@ type RequestResult = { errorMessage?: string; }; -export function post(url: URL, body: T, options?: Partial, compressPayload?: boolean): Promise { +export function post( + url: URL, + body: T, + options?: Partial, + compressPayload?: boolean, +): Promise { const bodyJSON = JSON.stringify(body); let buffer = Buffer.from(bodyJSON);