-
Notifications
You must be signed in to change notification settings - Fork 386
Expand file tree
/
Copy pathcpu.js
More file actions
126 lines (97 loc) · 2.75 KB
/
cpu.js
File metadata and controls
126 lines (97 loc) · 2.75 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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
'use strict'
const { storage } = require('../../../../datadog-core')
const dc = require('../../../../diagnostics_channel')
const beforeCh = dc.channel('dd-trace:storage:before')
const afterCh = dc.channel('dd-trace:storage:after')
function getActiveSpan () {
const store = storage.getStore()
if (!store) return
return store.span
}
function getStartedSpans (activeSpan) {
const context = activeSpan.context()
if (!context) return
return context._trace.started
}
function getSpanContextTags (span) {
return span.context()._tags
}
function isWebServerSpan (tags) {
return tags['span.type'] === 'web'
}
function endpointNameFromTags (tags) {
return tags['resource.name'] || [
tags['http.method'],
tags['http.route']
].filter(v => v).join(' ')
}
class NativeCpuProfiler {
constructor (options = {}) {
this.type = 'cpu'
this._frequency = options.frequency || 99
this._mapper = undefined
this._pprof = undefined
this._started = false
this._cpuProfiler = undefined
this._endpointCollection = options.endpointCollection
// Bind to this so the same value can be used to unsubscribe later
this._enter = this._enter.bind(this)
this._exit = this._exit.bind(this)
}
_enter () {
if (!this._cpuProfiler) return
const active = getActiveSpan()
if (!active) return
const activeCtx = active.context()
if (!activeCtx) return
const spans = getStartedSpans(active)
if (!spans || !spans.length) return
const firstCtx = spans[0].context()
if (!firstCtx) return
const labels = {
'local root span id': firstCtx.toSpanId(),
'span id': activeCtx.toSpanId()
}
if (this._endpointCollection) {
const webServerTags = spans
.map(getSpanContextTags)
.filter(isWebServerSpan)[0]
if (webServerTags) {
labels['trace endpoint'] = endpointNameFromTags(webServerTags)
}
}
this._cpuProfiler.labels = labels
}
_exit () {
if (!this._cpuProfiler) return
this._cpuProfiler.labels = {}
}
start ({ mapper } = {}) {
if (this._started) return
this._started = true
this._mapper = mapper
if (!this._pprof) {
this._pprof = require('@datadog/pprof')
this._cpuProfiler = new this._pprof.CpuProfiler()
}
this._cpuProfiler.start(this._frequency)
this._enter()
beforeCh.subscribe(this._enter)
afterCh.subscribe(this._exit)
}
profile () {
if (!this._started) return
return this._cpuProfiler.profile()
}
encode (profile) {
return this._pprof.encode(profile)
}
stop () {
if (!this._started) return
this._started = false
this._cpuProfiler.stop()
beforeCh.unsubscribe(this._enter)
afterCh.unsubscribe(this._exit)
}
}
module.exports = NativeCpuProfiler