|
10 | 10 |
|
11 | 11 | const nock = require('nock') |
12 | 12 |
|
| 13 | +const { createNativeSpanDrain } = require('../native-span-drain') |
| 14 | + |
13 | 15 | nock.disableNetConnect() |
14 | 16 | nock('http://127.0.0.1:8126').persist().put(/.*/).reply(200, '{}').post(/.*/).reply(200, '{}') |
15 | 17 |
|
16 | 18 | const tracer = require('../../..').init({ hostname: '127.0.0.1', port: 8126 }) |
17 | 19 |
|
18 | | -const nativeSpans = tracer._tracer._nativeSpans |
19 | | -const pendingNativeIds = nativeSpans ? [] : null |
| 20 | +const nativeSpanDrain = createNativeSpanDrain(tracer) |
20 | 21 |
|
21 | 22 | tracer._tracer._processor.process = function (span) { |
22 | | - if (pendingNativeIds) { |
23 | | - pendingNativeIds.push(span.context()._nativeSpanId) |
24 | | - } |
| 23 | + nativeSpanDrain.add(span) |
25 | 24 | this._erase(span.context()._trace, []) |
26 | 25 | } |
27 | 26 |
|
28 | | -// Extract the accumulated spans (bounds the WASM map) and drain the staged |
29 | | -// chunk via a mocked-agent send (bounds prepared-chunk memory). Span ids are |
30 | | -// 8-byte u64 LE. |
31 | | -async function drainNative () { |
32 | | - if (!pendingNativeIds || pendingNativeIds.length === 0) return |
33 | | - nativeSpans.flushChangeQueue() |
34 | | - const buf = Buffer.alloc(pendingNativeIds.length * 8) |
35 | | - let idx = 0 |
36 | | - for (const spanId of pendingNativeIds) { |
37 | | - buf.set(spanId, idx) |
38 | | - idx += 8 |
39 | | - } |
40 | | - nativeSpans._state.prepareChunk(pendingNativeIds.length, false, buf) |
41 | | - await nativeSpans._state.sendPreparedChunk().catch(() => {}) |
42 | | - pendingNativeIds.length = 0 |
43 | | -} |
44 | | - |
45 | 27 | const ITERATIONS = 1_000_000 |
46 | 28 |
|
47 | | -// Pre-create spans with tags, then measure read cost in a separate loop |
48 | | -// to isolate reads from writes. |
49 | | -const spans = new Array(1000) |
50 | | -for (let i = 0; i < spans.length; i++) { |
51 | | - spans[i] = tracer.startSpan('bench.gettag', { |
52 | | - tags: { |
53 | | - 'http.method': 'GET', |
54 | | - 'http.url': 'https://api.example.com/users/123', |
55 | | - 'http.status_code': 200, |
56 | | - 'service.name': 'my-service', |
57 | | - 'resource.name': 'GET /users/:id', |
58 | | - }, |
59 | | - }) |
60 | | -} |
| 29 | +async function main () { |
| 30 | + // Pre-create spans with tags, then measure read cost in a separate loop |
| 31 | + // to isolate reads from writes. |
| 32 | + const spans = new Array(1000) |
| 33 | + for (let i = 0; i < spans.length; i++) { |
| 34 | + spans[i] = tracer.startSpan('bench.gettag', { |
| 35 | + tags: { |
| 36 | + 'http.method': 'GET', |
| 37 | + 'http.url': 'https://api.example.com/users/123', |
| 38 | + 'http.status_code': 200, |
| 39 | + 'service.name': 'my-service', |
| 40 | + 'resource.name': 'GET /users/:id', |
| 41 | + }, |
| 42 | + }) |
| 43 | + } |
61 | 44 |
|
62 | | -// Read tags in a tight loop across the pre-created spans |
63 | | -for (let i = 0; i < ITERATIONS; i++) { |
64 | | - const span = spans[i % spans.length] |
65 | | - const ctx = span.context() |
| 45 | + // Read tags in a tight loop across the pre-created spans |
| 46 | + for (let i = 0; i < ITERATIONS; i++) { |
| 47 | + const span = spans[i % spans.length] |
| 48 | + const ctx = span.context() |
66 | 49 |
|
67 | | - // Individual reads (common in plugin code) |
68 | | - ctx.getTag('http.method') |
69 | | - ctx.getTag('http.status_code') |
70 | | - ctx.getTag('resource.name') |
71 | | -} |
| 50 | + // Individual reads (common in plugin code) |
| 51 | + ctx.getTag('http.method') |
| 52 | + ctx.getTag('http.status_code') |
| 53 | + ctx.getTag('resource.name') |
| 54 | + } |
72 | 55 |
|
73 | | -// Clean up |
74 | | -for (const span of spans) { |
75 | | - span.finish() |
| 56 | + // Clean up |
| 57 | + for (const span of spans) { |
| 58 | + span.finish() |
| 59 | + } |
| 60 | + await nativeSpanDrain.drain() |
76 | 61 | } |
77 | | -drainNative() |
| 62 | + |
| 63 | +main() |
0 commit comments