-
Notifications
You must be signed in to change notification settings - Fork 406
Expand file tree
/
Copy pathindex.js
More file actions
79 lines (68 loc) · 3.17 KB
/
Copy pathindex.js
File metadata and controls
79 lines (68 loc) · 3.17 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
'use strict'
const assert = require('node:assert/strict')
const guard = require('../startup-guard')
// Full traced redis command, end to end. Where the isolated plugin-redis bench
// stubs startSpan to measure only the meta assembly, this drives the real tracer
// and the real redis plugin over the diagnostic channels the instrumentation
// uses, so each iteration pays the whole per-command cost: bindStart meta build,
// span start, context entry via runStores, span finish and the real processor
// (priority/span sampling, git-metadata tagging, span formatting and stats).
// Only the exporter is swapped for a no-op, so the processor still formats and
// erases each finished trace but nothing is buffered, encoded, or leaves the
// process.
const tracer = require('../../..').init()
tracer._tracer._processor._exporter = { export () {} }
const RedisPlugin = require('../../../packages/datadog-plugin-redis/src/index')
const { channel } = require('../../../packages/datadog-instrumentations/src/helpers/instrument')
// Construct the real plugin against the real tracer + tracer config (the pair the
// plugin manager would pass) and enable it, which subscribes bindStart/bindFinish
// to the redis channels. tracer.use('redis') alone would not: the plugin only
// subscribes once the redis module loads, and there is no client here.
const plugin = new RedisPlugin(tracer, tracer._pluginManager._tracerConfig)
plugin.configure({ enabled: true, service: 'redis-prod' })
const startCh = channel('apm:redis:command:start')
const finishCh = channel('apm:redis:command:finish')
const OPERATIONS = Number(process.env.OPERATIONS)
const CONN = { host: 'redis-primary.internal', port: 6379 }
const COMMANDS = [
{ command: 'get', args: ['user:1234567:profile'] },
{ command: 'set', args: ['session:abcdef', 'active', 'EX', 3600] },
{ command: 'hset', args: ['user:1234567', 'name', 'Jane', 'email', 'jane@example.com'] },
{ command: 'get', args: ['cart:99887766'] },
]
const len = COMMANDS.length
/**
* A fresh per-command context, matching what the instrumentation's getStartCtx
* allocates per call: runStores writes the span store onto it, so it cannot be
* reused across commands.
*
* @param {{ command: string, args: unknown[] }} cmd
*/
function makeCtx (cmd) {
return {
db: 0,
command: cmd.command,
args: cmd.args,
argsStartIndex: 0,
connectionOptions: CONN,
connectionName: 'default',
}
}
const NOOP = () => {}
// Pre-flight: one full command must create, tag and finish a real span.
const preCtx = makeCtx(COMMANDS[0])
startCh.runStores(preCtx, NOOP)
const preSpan = preCtx.currentStore?.span
assert.ok(preSpan, 'start channel did not create a span (plugin not subscribed?)')
assert.equal(preSpan.context().getTag('db.type'), 'redis', 'span is missing the redis meta')
finishCh.publish(preCtx)
assert.ok(preSpan._duration !== undefined, 'finish channel did not finish the span')
guard.loopStart()
for (let i = 0; i < OPERATIONS; i++) {
const ctx = makeCtx(COMMANDS[i % len])
startCh.runStores(ctx, NOOP)
finishCh.publish(ctx)
}
// The full traced lifecycle cannot grow enough to meet the default startup
// share without exceeding the benchmark runtime budget.
guard.done(0.18)