From 728c26fca2c5efd0f03910f5ee311f9de24f3d1e Mon Sep 17 00:00:00 2001 From: Richard Marmorstein Date: Tue, 12 Dec 2023 14:57:06 -0800 Subject: [PATCH 1/6] Ability to pass usage on stripeMethod "spec" --- src/RequestSender.ts | 43 ++++++++++++++++++++++++++++++------- src/StripeResource.ts | 3 +++ src/Types.d.ts | 4 ++++ test/StripeResource.spec.ts | 23 ++++++++++++++++++++ test/testUtils.ts | 10 ++++++++- 5 files changed, 74 insertions(+), 9 deletions(-) diff --git a/src/RequestSender.ts b/src/RequestSender.ts index 288d02353d..d69c3c0b87 100644 --- a/src/RequestSender.ts +++ b/src/RequestSender.ts @@ -88,6 +88,7 @@ export class RequestSender { */ _streamingResponseHandler( requestEvent: RequestEvent, + usage: Array, callback: RequestCallback ): (res: HttpClientResponseInterface) => RequestCallbackReturn { return (res: HttpClientResponseInterface): RequestCallbackReturn => { @@ -102,7 +103,8 @@ export class RequestSender { this._stripe._emitter.emit('response', responseEvent); this._recordRequestMetrics( this._getRequestId(headers), - responseEvent.elapsed + responseEvent.elapsed, + usage ); }; @@ -122,7 +124,11 @@ export class RequestSender { * parses the JSON and returns it (i.e. passes it to the callback) if there * is no "error" field. Otherwise constructs/passes an appropriate Error. */ - _jsonResponseHandler(requestEvent: RequestEvent, callback: RequestCallback) { + _jsonResponseHandler( + requestEvent: RequestEvent, + usage: Array, + callback: RequestCallback + ) { return (res: HttpClientResponseInterface): void => { const headers = res.getHeaders(); const requestId = this._getRequestId(headers); @@ -180,7 +186,7 @@ export class RequestSender { ) .then( (jsonResponse) => { - this._recordRequestMetrics(requestId, responseEvent.elapsed); + this._recordRequestMetrics(requestId, responseEvent.elapsed, usage); // Expose raw response object. const rawResponse = res.getRawResponse(); @@ -387,7 +393,11 @@ export class RequestSender { } } - _recordRequestMetrics(requestId: string, requestDurationMs: number): void { + _recordRequestMetrics( + requestId: string, + requestDurationMs: number, + usage: Array + ): void { if (this._stripe.getTelemetryEnabled() && requestId) { if ( this._stripe._prevRequestMetrics.length > this._maxBufferedRequestMetric @@ -396,10 +406,18 @@ export class RequestSender { 'Request metrics buffer is full, dropping telemetry message.' ); } else { - this._stripe._prevRequestMetrics.push({ + const m: { + request_id: string; + request_duration_ms: number; + usage?: Array; + } = { request_id: requestId, request_duration_ms: requestDurationMs, - }); + }; + if (usage && usage.length > 0) { + m.usage = usage; + } + this._stripe._prevRequestMetrics.push(m); } } } @@ -411,6 +429,7 @@ export class RequestSender { data: RequestData, auth: string | null, options: RequestOptions = {}, + usage: Array = [], callback: RequestCallback, requestDataProcessor: RequestDataProcessor | null = null ): void { @@ -488,9 +507,17 @@ export class RequestSender { res.getHeaders()['retry-after'] ); } else if (options.streaming && res.getStatusCode() < 400) { - return this._streamingResponseHandler(requestEvent, callback)(res); + return this._streamingResponseHandler( + requestEvent, + usage, + callback + )(res); } else { - return this._jsonResponseHandler(requestEvent, callback)(res); + return this._jsonResponseHandler( + requestEvent, + usage, + callback + )(res); } }) .catch((error: HttpClientResponseError) => { diff --git a/src/StripeResource.ts b/src/StripeResource.ts index d8d5cf130f..fc7610eecc 100644 --- a/src/StripeResource.ts +++ b/src/StripeResource.ts @@ -122,6 +122,7 @@ StripeResource.prototype = { ): RequestOpts { // Extract spec values with defaults. const requestMethod = (spec.method || 'GET').toUpperCase(); + const usage = spec.usage || []; const urlParams = spec.urlParams || []; const encode = spec.encode || ((data): RequestData => data); @@ -190,6 +191,7 @@ StripeResource.prototype = { host: host ?? null, streaming, settings: options.settings, + usage, }; }, @@ -238,6 +240,7 @@ StripeResource.prototype = { opts.bodyData, opts.auth, {headers, settings, streaming: opts.streaming}, + opts.usage, requestCallback, this.requestDataProcessor?.bind(this) ); diff --git a/src/Types.d.ts b/src/Types.d.ts index 2ccfc64234..f6ab743848 100644 --- a/src/Types.d.ts +++ b/src/Types.d.ts @@ -24,6 +24,7 @@ export type MethodSpec = { streaming?: boolean; host?: string; transformResponseData?: (response: HttpClientResponseInterface) => any; + usage?: Array; }; export type MultipartRequestData = RequestData | StreamingFile | BufferedFile; export type RawErrorType = @@ -49,6 +50,7 @@ export type RequestEvent = { method?: string; path?: string; request_start_time: number; + usage: Array; }; export type RequestHeaders = Record; export type RequestOptions = { @@ -66,6 +68,7 @@ export type RequestOpts = { host: string | null; streaming: boolean; settings: RequestSettings; + usage: Array; }; export type RequestSettings = {timeout?: number; maxNetworkRetries?: number}; export type ResponseEvent = { @@ -155,6 +158,7 @@ export type RequestSender = { data: RequestData, auth: string | null, options: RequestOptions, + usage: Array, callback: RequestCallback, requestDataProcessor: RequestDataProcessor | undefined ): void; diff --git a/test/StripeResource.spec.ts b/test/StripeResource.spec.ts index a7a0b60887..80f09c0758 100644 --- a/test/StripeResource.spec.ts +++ b/test/StripeResource.spec.ts @@ -262,4 +262,27 @@ describe('StripeResource', () => { ]); }); }); + + describe('usage', () => { + it('is passed to the request sender', (callback) => { + const mockSelf = new (StripeResource.extend({ + boop: stripeMethod({ + method: 'GET', + fullPath: '/v1/widgets/{widget}/boop', + usage: ['llama', 'bufo'], + }), + }))(stripe); + + mockSelf.boop('foo', {bar: 'baz'}, (err, res) => { + if (err) { + return callback(err); + } + expect(stripe._requestSender._stripe.LAST_REQUEST.usage).to.deep.equal([ + 'llama', + 'bufo', + ]); + return callback(); + }); + }); + }); }); diff --git a/test/testUtils.ts b/test/testUtils.ts index ecbf9a37a8..4d798ec6f7 100644 --- a/test/testUtils.ts +++ b/test/testUtils.ts @@ -117,6 +117,7 @@ export const getMockStripe = ( data: RequestData, auth: string | null, options: RequestOptions = {}, + usage: Array, callback: RequestCallback, requestDataProcessor: RequestDataProcessor | null = null ) { @@ -127,6 +128,7 @@ export const getMockStripe = ( data, auth, options, + usage, callback, requestDataProcessor ); @@ -149,7 +151,7 @@ export const getMockStripe = ( export const createMockClient = ( requests: Array<{method: string; path: string; response: string}> ): StripeClient => { - return getMockStripe({}, (method, _host, path, _4, _5, _6, callback) => { + return getMockStripe({}, (method, _host, path, _4, _5, _6, _7, callback) => { const request = requests.find((r) => r.method == method && r.path == path); if (!request) { throw new Error(`Unable to find a mock request for ${method} ${path}`); @@ -170,6 +172,7 @@ export const getSpyableStripe = ( data: RequestData, auth: string | null, options: RequestOptions = {}, + usage: Array = [], callback: RequestCallback, requestDataProcessor: RequestDataProcessor | null = null ) { @@ -181,6 +184,7 @@ export const getSpyableStripe = ( settings: RequestSettings; auth?: string; host?: string; + usage?: Array; }; const req: LastRequest = (stripeInstance.LAST_REQUEST = { method, @@ -189,6 +193,9 @@ export const getSpyableStripe = ( headers: options.headers || {}, settings: options.settings || {}, }); + if (usage && usage.length > 1) { + req.usage = usage; + } if (auth) { req.auth = auth; } @@ -217,6 +224,7 @@ export const getSpyableStripe = ( data, auth, options, + usage, callback, requestDataProcessor ); From 175c52d7410cf6466950add04c32ea5d9e0a55a9 Mon Sep 17 00:00:00 2001 From: Richard Marmorstein Date: Wed, 13 Dec 2023 00:00:30 -0800 Subject: [PATCH 2/6] README update --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index eb822ee4c3..47d2191137 100644 --- a/README.md +++ b/README.md @@ -197,7 +197,7 @@ const stripe = Stripe('sk_test_...', { | `host` | `'api.stripe.com'` | Host that requests are made to. | | `port` | 443 | Port that requests are made to. | | `protocol` | `'https'` | `'https'` or `'http'`. `http` is never appropriate for sending requests to Stripe servers, and we strongly discourage `http`, even in local testing scenarios, as this can result in your credentials being transmitted over an insecure channel. | -| `telemetry` | `true` | Allow Stripe to send latency [telemetry](#request-latency-telemetry). | +| `telemetry` | `true` | Allow Stripe to send [telemetry](#telemetry). | > **Note** > Both `maxNetworkRetries` and `timeout` can be overridden on a per-request basis. @@ -477,10 +477,12 @@ const allNewCustomers = await stripe.customers .autoPagingToArray({limit: 10000}); ``` -### Request latency telemetry +### Telemetry -By default, the library sends request latency telemetry to Stripe. These -numbers help Stripe improve the overall latency of its API for all users. +By default, the library sends request telemetry to Stripe regarding request +latency and feature usage. These +numbers help Stripe improve the overall latency of its API for all users, and +improve popular features. You can disable this behavior if you prefer: From 287a9fa294d9a5be06dcad9f8ba6b3f457a641b7 Mon Sep 17 00:00:00 2001 From: Richard Marmorstein Date: Wed, 13 Dec 2023 00:34:16 -0800 Subject: [PATCH 3/6] fixup! Ability to pass usage on stripeMethod "spec" --- test/autoPagination.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/autoPagination.spec.ts b/test/autoPagination.spec.ts index 2946dff2f4..1c5f99db1e 100644 --- a/test/autoPagination.spec.ts +++ b/test/autoPagination.spec.ts @@ -41,7 +41,7 @@ describe('auto pagination', () => { const mockStripe = getMockStripe( {}, - (_1, _2, path, _4, _5, _6, callback) => { + (_1, _2, path, _4, _5, _6, _7, callback) => { paramsLog.push(path.slice(path.indexOf('?'))); callback( null, @@ -661,7 +661,7 @@ describe('auto pagination', () => { const mockStripe = getMockStripe( {}, - (_1, _2, path, _4, _5, _6, callback) => { + (_1, _2, path, _4, _5, _6, _7, callback) => { paramsLog.push(path.slice(path.indexOf('?'))); callback( From 9ca217fd8a64978aa4b2eabb851e944e3f798fa1 Mon Sep 17 00:00:00 2001 From: Richard Marmorstein Date: Wed, 13 Dec 2023 09:59:10 -0800 Subject: [PATCH 4/6] More extensive test --- test/telemetry.spec.ts | 61 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/test/telemetry.spec.ts b/test/telemetry.spec.ts index c91ca11a92..f532a34db6 100644 --- a/test/telemetry.spec.ts +++ b/test/telemetry.spec.ts @@ -3,6 +3,7 @@ import http = require('http'); import {expect} from 'chai'; import {FAKE_API_KEY} from './testUtils.js'; +import {StripeResource} from '../src/StripeResource.js'; let testServer = null; function createTestServer(handlerFunc, cb) { @@ -124,6 +125,66 @@ describe('Client Telemetry', () => { } ); }); + it('Sends usage telemetry when registered', (done) => { + let numRequests = 0; + + createTestServer( + (req, res) => { + numRequests += 1; + + const telemetry = req.headers['x-stripe-client-telemetry']; + + switch (numRequests) { + case 1: + expect(telemetry).to.not.exist; + break; + case 2: + expect(telemetry).to.exist; + expect( + JSON.parse(telemetry).last_request_metrics.request_id + ).to.equal('req_1'); + expect( + JSON.parse(telemetry).last_request_metrics.usage + ).to.deep.equal(['llama', 'bufo' ]); + break; + default: + expect.fail(`Should not have reached request ${numRequests}`); + } + + res.setHeader('Request-Id', `req_${numRequests}`); + res.writeHead(200, {'Content-Type': 'application/json'}); + res.end('{}'); + }, + (host, port) => { + const stripe = require('../src/stripe.cjs.node.js')( + 'sk_test_FEiILxKZwnmmocJDUjUNO6pa', + { + telemetry: true, + host, + port, + protocol: 'http', + } + ); + + const resource = new (StripeResource.extend({ + boop: StripeResource.method({ + method: 'POST', + fullPath: '/v1/widgets/{widget}/boop', + usage: ['llama', 'bufo' ], + })}))(stripe) + + return Promise.resolve() + .then(() => resource.boop('w_123')) + .then(() => resource.boop('w_123')) + .then(() => { + expect(numRequests).to.equal(2); + }) + .catch(done) + .then(() => done()) + + } + ); + }); it('Buffers metrics on concurrent requests', (done) => { let numRequests = 0; From f1c52bd8b41af7adc2ea8e87b62626400da57d5e Mon Sep 17 00:00:00 2001 From: Richard Marmorstein Date: Wed, 13 Dec 2023 11:21:02 -0800 Subject: [PATCH 5/6] Async the test --- test/telemetry.spec.ts | 361 +++++++++++++++++++---------------------- 1 file changed, 168 insertions(+), 193 deletions(-) diff --git a/test/telemetry.spec.ts b/test/telemetry.spec.ts index f532a34db6..3c665c9f8b 100644 --- a/test/telemetry.spec.ts +++ b/test/telemetry.spec.ts @@ -6,11 +6,16 @@ import {FAKE_API_KEY} from './testUtils.js'; import {StripeResource} from '../src/StripeResource.js'; let testServer = null; -function createTestServer(handlerFunc, cb) { +const createTestServer = ( + handlerFunc: ( + req: http.IncomingMessage, + res: http.ServerResponse + ) => Promise +) => { const host = '127.0.0.1'; - testServer = http.createServer((req, res) => { + testServer = http.createServer(async (req, res) => { try { - handlerFunc(req, res); + await handlerFunc(req, res); } catch (e) { res.writeHead(400, {'Content-Type': 'application/json'}); res.end( @@ -20,11 +25,13 @@ function createTestServer(handlerFunc, cb) { ); } }); - testServer.listen(0, host, () => { - const port = testServer.address().port; - cb(host, port); + return new Promise((resolve) => { + testServer.listen(0, host, () => { + const port = testServer.address().port; + resolve({host, port}); + }); }); -} +}; describe('Client Telemetry', () => { afterEach(() => { @@ -34,208 +41,176 @@ describe('Client Telemetry', () => { } }); - it('Does not send telemetry when disabled', (done) => { + it('Does not send telemetry when disabled', async () => { let numRequests = 0; - createTestServer( - (req, res) => { - numRequests += 1; - - const telemetry = req.headers['x-stripe-client-telemetry']; - - switch (numRequests) { - case 1: - case 2: - expect(telemetry).to.not.exist; - break; - default: - expect.fail(`Should not have reached request ${numRequests}`); - } - - res.setHeader('Request-Id', `req_${numRequests}`); - res.writeHead(200, {'Content-Type': 'application/json'}); - res.end('{}'); - }, - (host, port) => { - const stripe = require('../src/stripe.cjs.node.js')(FAKE_API_KEY, { - telemetry: false, - host, - port, - protocol: 'http', - }); - - stripe.balance - .retrieve() - .then((res) => stripe.balance.retrieve()) - .then((res) => { - expect(numRequests).to.equal(2); - done(); - }) - .catch(done); + const handle = (req, res) => { + numRequests += 1; + + const telemetry = req.headers['x-stripe-client-telemetry']; + + switch (numRequests) { + case 1: + case 2: + expect(telemetry).to.not.exist; + break; + default: + expect.fail(`Should not have reached request ${numRequests}`); } - ); + + res.setHeader('Request-Id', `req_${numRequests}`); + res.writeHead(200, {'Content-Type': 'application/json'}); + res.end('{}'); + }; + + const {host, port} = await createTestServer(handle); + const stripe = require('../src/stripe.cjs.node.js')(FAKE_API_KEY, { + telemetry: false, + host, + port, + protocol: 'http', + }); + + await stripe.balance.retrieve(); + await stripe.balance.retrieve(); + expect(numRequests).to.equal(2); }); - it('Sends client telemetry on the second request when enabled', (done) => { + it('Sends client telemetry on the second request when enabled', async () => { let numRequests = 0; + const handle = (req, res) => { + numRequests += 1; + + const telemetry = req.headers['x-stripe-client-telemetry']; + + switch (numRequests) { + case 1: + expect(telemetry).to.not.exist; + break; + case 2: + expect(telemetry).to.exist; + expect( + JSON.parse(telemetry).last_request_metrics.request_id + ).to.equal('req_1'); + break; + default: + expect.fail(`Should not have reached request ${numRequests}`); + } - createTestServer( - (req, res) => { - numRequests += 1; - - const telemetry = req.headers['x-stripe-client-telemetry']; - - switch (numRequests) { - case 1: - expect(telemetry).to.not.exist; - break; - case 2: - expect(telemetry).to.exist; - expect( - JSON.parse(telemetry).last_request_metrics.request_id - ).to.equal('req_1'); - break; - default: - expect.fail(`Should not have reached request ${numRequests}`); - } - - res.setHeader('Request-Id', `req_${numRequests}`); - res.writeHead(200, {'Content-Type': 'application/json'}); - res.end('{}'); - }, - (host, port) => { - const stripe = require('../src/stripe.cjs.node.js')( - 'sk_test_FEiILxKZwnmmocJDUjUNO6pa', - { - telemetry: true, - host, - port, - protocol: 'http', - } - ); - - stripe.balance - .retrieve() - .then((res) => stripe.balance.retrieve()) - .then((res) => { - expect(numRequests).to.equal(2); - done(); - }) - .catch(done); + res.setHeader('Request-Id', `req_${numRequests}`); + res.writeHead(200, {'Content-Type': 'application/json'}); + res.end('{}'); + }; + const {host, port} = await createTestServer(handle); + const stripe = require('../src/stripe.cjs.node.js')( + 'sk_test_FEiILxKZwnmmocJDUjUNO6pa', + { + telemetry: true, + host, + port, + protocol: 'http', } ); + + await stripe.balance.retrieve(); + await stripe.balance.retrieve(); + expect(numRequests).to.equal(2); }); - it('Sends usage telemetry when registered', (done) => { + it('Sends usage telemetry when registered', async () => { let numRequests = 0; - createTestServer( - (req, res) => { - numRequests += 1; - - const telemetry = req.headers['x-stripe-client-telemetry']; - - switch (numRequests) { - case 1: - expect(telemetry).to.not.exist; - break; - case 2: - expect(telemetry).to.exist; - expect( - JSON.parse(telemetry).last_request_metrics.request_id - ).to.equal('req_1'); - expect( - JSON.parse(telemetry).last_request_metrics.usage - ).to.deep.equal(['llama', 'bufo' ]); - break; - default: - expect.fail(`Should not have reached request ${numRequests}`); - } - - res.setHeader('Request-Id', `req_${numRequests}`); - res.writeHead(200, {'Content-Type': 'application/json'}); - res.end('{}'); - }, - (host, port) => { - const stripe = require('../src/stripe.cjs.node.js')( - 'sk_test_FEiILxKZwnmmocJDUjUNO6pa', - { - telemetry: true, - host, - port, - protocol: 'http', - } - ); - - const resource = new (StripeResource.extend({ - boop: StripeResource.method({ - method: 'POST', - fullPath: '/v1/widgets/{widget}/boop', - usage: ['llama', 'bufo' ], - })}))(stripe) - - return Promise.resolve() - .then(() => resource.boop('w_123')) - .then(() => resource.boop('w_123')) - .then(() => { - expect(numRequests).to.equal(2); - }) - .catch(done) - .then(() => done()) + const handle = (req, res) => { + numRequests += 1; + + const telemetry = req.headers['x-stripe-client-telemetry']; + + switch (numRequests) { + case 1: + expect(telemetry).to.not.exist; + break; + case 2: + expect(telemetry).to.exist; + expect( + JSON.parse(telemetry).last_request_metrics.request_id + ).to.equal('req_1'); + expect( + JSON.parse(telemetry).last_request_metrics.usage + ).to.deep.equal(['llama', 'bufo']); + break; + default: + expect.fail(`Should not have reached request ${numRequests}`); + } + res.setHeader('Request-Id', `req_${numRequests}`); + res.writeHead(200, {'Content-Type': 'application/json'}); + res.end('{}'); + }; + + const {host, port} = await createTestServer(handle); + const stripe = require('../src/stripe.cjs.node.js')( + 'sk_test_FEiILxKZwnmmocJDUjUNO6pa', + { + telemetry: true, + host, + port, + protocol: 'http', } ); + + const resource = new (StripeResource.extend({ + boop: StripeResource.method({ + method: 'POST', + fullPath: '/v1/widgets/{widget}/boop', + usage: ['llama', 'bufo'], + }), + }))(stripe); + + await resource.boop('w_123'); + await resource.boop('w_123'); + expect(numRequests).to.equal(2); }); +}); - it('Buffers metrics on concurrent requests', (done) => { - let numRequests = 0; +it('Buffers metrics on concurrent requests', async () => { + let numRequests = 0; + + const handle = (req, res) => { + numRequests += 1; + + const telemetry = req.headers['x-stripe-client-telemetry']; + + switch (numRequests) { + case 1: + case 2: + expect(telemetry).to.not.exist; + break; + case 3: + case 4: + expect(telemetry).to.exist; + expect( + JSON.parse(telemetry).last_request_metrics.request_id + ).to.be.oneOf(['req_1', 'req_2']); + break; + default: + expect.fail(`Should not have reached request ${numRequests}`); + } - createTestServer( - (req, res) => { - numRequests += 1; - - const telemetry = req.headers['x-stripe-client-telemetry']; - - switch (numRequests) { - case 1: - case 2: - expect(telemetry).to.not.exist; - break; - case 3: - case 4: - expect(telemetry).to.exist; - expect( - JSON.parse(telemetry).last_request_metrics.request_id - ).to.be.oneOf(['req_1', 'req_2']); - break; - default: - expect.fail(`Should not have reached request ${numRequests}`); - } - - res.setHeader('Request-Id', `req_${numRequests}`); - res.writeHead(200, {'Content-Type': 'application/json'}); - res.end('{}'); - }, - (host, port) => { - const stripe = require('../src/stripe.cjs.node.js')( - 'sk_test_FEiILxKZwnmmocJDUjUNO6pa', - { - telemetry: true, - host, - port, - protocol: 'http', - } - ); - - Promise.all([stripe.balance.retrieve(), stripe.balance.retrieve()]) - .then(() => - Promise.all([stripe.balance.retrieve(), stripe.balance.retrieve()]) - ) - .then(() => { - expect(numRequests).to.equal(4); - done(); - }) - .catch(done); - } - ); - }); + res.setHeader('Request-Id', `req_${numRequests}`); + res.writeHead(200, {'Content-Type': 'application/json'}); + res.end('{}'); + }; + const {host, port} = await createTestServer(handle); + const stripe = require('../src/stripe.cjs.node.js')( + 'sk_test_FEiILxKZwnmmocJDUjUNO6pa', + { + telemetry: true, + host, + port, + protocol: 'http', + } + ); + + await Promise.all([stripe.balance.retrieve(), stripe.balance.retrieve()]); + await Promise.all([stripe.balance.retrieve(), stripe.balance.retrieve()]); + expect(numRequests).to.equal(4); }); From 456f6e01c9a9cf067b8d4fce218938515adfe3d5 Mon Sep 17 00:00:00 2001 From: Richard Marmorstein Date: Thu, 14 Dec 2023 15:42:52 -0800 Subject: [PATCH 6/6] fix test --- test/telemetry.spec.ts | 82 +++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/test/telemetry.spec.ts b/test/telemetry.spec.ts index 3c665c9f8b..b3cdceb0ca 100644 --- a/test/telemetry.spec.ts +++ b/test/telemetry.spec.ts @@ -169,48 +169,48 @@ describe('Client Telemetry', () => { await resource.boop('w_123'); expect(numRequests).to.equal(2); }); -}); -it('Buffers metrics on concurrent requests', async () => { - let numRequests = 0; - - const handle = (req, res) => { - numRequests += 1; - - const telemetry = req.headers['x-stripe-client-telemetry']; - - switch (numRequests) { - case 1: - case 2: - expect(telemetry).to.not.exist; - break; - case 3: - case 4: - expect(telemetry).to.exist; - expect( - JSON.parse(telemetry).last_request_metrics.request_id - ).to.be.oneOf(['req_1', 'req_2']); - break; - default: - expect.fail(`Should not have reached request ${numRequests}`); - } + it('Buffers metrics on concurrent requests', async () => { + let numRequests = 0; - res.setHeader('Request-Id', `req_${numRequests}`); - res.writeHead(200, {'Content-Type': 'application/json'}); - res.end('{}'); - }; - const {host, port} = await createTestServer(handle); - const stripe = require('../src/stripe.cjs.node.js')( - 'sk_test_FEiILxKZwnmmocJDUjUNO6pa', - { - telemetry: true, - host, - port, - protocol: 'http', - } - ); + const handle = (req, res) => { + numRequests += 1; + + const telemetry = req.headers['x-stripe-client-telemetry']; + + switch (numRequests) { + case 1: + case 2: + expect(telemetry).to.not.exist; + break; + case 3: + case 4: + expect(telemetry).to.exist; + expect( + JSON.parse(telemetry).last_request_metrics.request_id + ).to.be.oneOf(['req_1', 'req_2']); + break; + default: + expect.fail(`Should not have reached request ${numRequests}`); + } + + res.setHeader('Request-Id', `req_${numRequests}`); + res.writeHead(200, {'Content-Type': 'application/json'}); + res.end('{}'); + }; + const {host, port} = await createTestServer(handle); + const stripe = require('../src/stripe.cjs.node.js')( + 'sk_test_FEiILxKZwnmmocJDUjUNO6pa', + { + telemetry: true, + host, + port, + protocol: 'http', + } + ); - await Promise.all([stripe.balance.retrieve(), stripe.balance.retrieve()]); - await Promise.all([stripe.balance.retrieve(), stripe.balance.retrieve()]); - expect(numRequests).to.equal(4); + await Promise.all([stripe.balance.retrieve(), stripe.balance.retrieve()]); + await Promise.all([stripe.balance.retrieve(), stripe.balance.retrieve()]); + expect(numRequests).to.equal(4); + }); });