diff --git a/src/index.spec.ts b/src/index.spec.ts index 17f226e2..87ba4280 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,11 @@ 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 +168,11 @@ 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 +194,11 @@ 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 +220,11 @@ 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/metrics/api.spec.ts b/src/metrics/api.spec.ts index 72e7c0e8..bd924d68 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/"; @@ -31,7 +32,9 @@ describe("APIClient", () => { ]; const scope = nock(baseAPIURL) - .post("/api/v1/distribution_points?api_key=api_key", JSON.stringify({ series: input })) + .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); @@ -41,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", 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); await expect(client.sendMetrics([])).rejects.toMatchInlineSnapshot(`"HTTP error code: 403"`); @@ -50,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", 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); await expect(client.sendMetrics([])).rejects.toMatchInlineSnapshot(`"Connection closed"`); diff --git a/src/metrics/api.ts b/src/metrics/api.ts index 446d2e91..f820dfc5 100644 --- a/src/metrics/api.ts +++ b/src/metrics/api.ts @@ -18,7 +18,7 @@ export class APIClient implements Client { 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 }); + 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 245d2176..24a57f84 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"; diff --git a/src/utils/request.ts b/src/utils/request.ts index ded6f94f..67dc70cf 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,23 @@ 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" },