import * as TestApp from '../../../test/App.js' import * as Containers from '../../../test/containers.js' import * as Metrics from '../../Metrics.js' import * as Analytics from '../Analytics.js' import * as RequestEvents from './requestEvents.js' describe('readBillableCounts', () => { test('counts separate requests and deduplicates redelivered analytics rows', async () => { const stack = await Containers.start() try { const analytics = Analytics.clickhouse({ database: 'tempo_api', password: 'clickhouse', url: `http://${stack.endpoints.clickhouse.host}:${stack.endpoints.clickhouse.port}`, user: 'clickhouse', }) await analytics.migrate() const rows: RequestEvents.Table[] = [] const app = TestApp.create({ auth: { keys: [{ ...TestApp.key, environment: 'production', scopes: ['data:read'] }], }, metrics: Metrics.cloudflare({ analytics: RequestEvents.createQueueSink({ async send(row) { rows.push(row) }, }), }), }) const responses = await Promise.all( [ '/v1/tokenlist', '/v1/tokenlist', '/v1/tokens/not-an-address', '/v1/indexer/query?query=SELECT%201', ].map(async (path) => app.request(path, { headers: { ...TestApp.auth.headers, 'tempo-request-id': 'client-controlled', 'X-Request-Id': 'client-controlled', }, }), ), ) expect(responses.map((response) => response.status)).toMatchInlineSnapshot(` [ 200, 200, 400, 403, ] `) expect(rows).toHaveLength(4) expect(new Set(rows.map((row) => row.request_id))).toEqual( new Set(responses.map((response) => response.headers.get('tempo-request-id'))), ) rows.push( { ...rows[0]!, error_code: null, request_id: 'request-payment-challenge', status: 402, }, { ...rows[0]!, error_code: 'payment_required', request_id: 'request-payment-unavailable', status: 429, }, ) const options = { environment: 'production', from: '2020-01-01T00:00:00.000Z', to: '2100-01-01T00:00:00.000Z', } as const await analytics.insert('request_events', rows) const counts = await RequestEvents.readBillableCounts(analytics, options) expect(counts.reduce((sum, row) => sum + row.count, 0)).toMatchInlineSnapshot(`3`) // Queue redelivery repeats the original rows, including their trusted request identities. await analytics.insert('request_events', rows) expect(await RequestEvents.readBillableCounts(analytics, options)).toEqual(counts) expect(await analytics.query('SELECT count() AS count FROM request_events')) .toMatchInlineSnapshot(` [ { "count": 12, }, ] `) } finally { await stack.stop() } }) })