forked from elastic/apm-agent-nodejs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathspan-compression.js
More file actions
215 lines (185 loc) · 6.25 KB
/
span-compression.js
File metadata and controls
215 lines (185 loc) · 6.25 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/*
* Copyright Elasticsearch B.V. and other contributors where applicable.
* Licensed under the BSD 2-Clause License; you may not use this file except in
* compliance with the BSD 2-Clause License.
*/
'use strict'
const STRATEGY_EXACT_MATCH = 'exact_match'
const STRATEGY_SAME_KIND = 'same_kind'
class SpanCompression {
constructor (agent) {
this._bufferedSpan = null
this._agent = agent
this.timestamp = null
this.duration = 0
this.composite = {
count: 0,
sum: 0,
compression_strategy: null
}
}
setBufferedSpan (span) {
this._bufferedSpan = span
}
getBufferedSpan () {
return this._bufferedSpan
}
// Compares two spans and returns which compression strategy to use
// or returns false if the second span can't be compressed into the
// first.
//
// @param Span compositeSpan
// @param Span toCompressSpan
// @returns boolean|String
_getCompressionStrategy (compositeSpan, toCompressSpan) {
if (!this._isEnabled() || !compositeSpan._serviceTarget || !toCompressSpan._serviceTarget) {
return false
}
const isSameKind = this.isSameKind(compositeSpan, toCompressSpan)
if (!isSameKind) {
return false
}
let strategy = STRATEGY_SAME_KIND
if (compositeSpan.name === toCompressSpan.name) {
strategy = STRATEGY_EXACT_MATCH
}
return strategy
}
isSameKind (compositeSpan, toCompressSpan) {
return compositeSpan.type === toCompressSpan.type &&
compositeSpan.subtype === toCompressSpan.subtype &&
compositeSpan._serviceTarget.type === toCompressSpan._serviceTarget.type &&
compositeSpan._serviceTarget.name === toCompressSpan._serviceTarget.name
}
// Sets initial composite values or confirms strategy matches
//
// Returns true if spanToCompress can be compressed into compositeSpan,
// returns false otherwise.
//
// @param Span compositeSpan
// @param Span spanToCompress
// @returns boolean
_initCompressionStrategy (compositeSpan, spanToCompress) {
if (!this.composite.compression_strategy) {
// If no strategy is set, check if strategizable or not. If so,
// set initial values. If not, bail.
this.composite.compression_strategy = this._getCompressionStrategy(
compositeSpan,
spanToCompress
)
if (!this.composite.compression_strategy) {
return false
}
// set initial composite context values
this.timestamp = compositeSpan.timestamp
this.composite.count = 1
this.composite.sum = compositeSpan._duration
} else {
// if so, compare with the compression strat and bail if mismatch
const strat = this._getCompressionStrategy(compositeSpan, spanToCompress)
if (strat !== this.composite.compression_strategy) {
return false
}
}
return true
}
// Attempts to compression the second span into the first
//
// @param Span compositeSpan
// @param Span spanToCompress
// @return boolean
tryToCompress (compositeSpan, spanToCompress) {
if (!this._isEnabled()) {
return false
}
// sets initial compression strategy value. returns
// false if not compression eligable
if (!this._initCompressionStrategy(compositeSpan, spanToCompress)) {
return false
}
const isAlreadyComposite = this.isComposite()
const canBeCompressed = isAlreadyComposite
? this.tryToCompressComposite(compositeSpan, spanToCompress)
: this.tryToCompressRegular(compositeSpan, spanToCompress)
if (!canBeCompressed) {
return false
}
if (!isAlreadyComposite) {
this.composite.count = 1
this.composite.sum = compositeSpan._duration
}
this.composite.count++
this.composite.sum += spanToCompress._duration
this.duration = (spanToCompress._endTimestamp - compositeSpan.timestamp) / 1000
return true
}
tryToCompressRegular (compositeSpan, spanToCompress) {
if (!this.isSameKind(compositeSpan, spanToCompress)) {
return false
}
if (compositeSpan.name === spanToCompress.name) {
if (this.duration <= (this._agent._conf.spanCompressionExactMatchMaxDuration * 1000) && spanToCompress._duration <= (this._agent._conf.spanCompressionExactMatchMaxDuration * 1000)) {
this.composite.compression_strategy = STRATEGY_EXACT_MATCH
return true
}
return false
}
if (this.duration <= (this._agent._conf.spanCompressionSameKindMaxDuration * 1000) && spanToCompress._duration <= (this._agent._conf.spanCompressionSameKindMaxDuration * 1000)) {
this.composite.compression_strategy = STRATEGY_SAME_KIND
compositeSpan.name = this._spanNameFromCompositeSpan(compositeSpan)
return true
}
return false
}
tryToCompressComposite (compositeSpan, spanToCompress) {
switch (this.composite.compression_strategy) {
case STRATEGY_EXACT_MATCH:
return this.isSameKind(compositeSpan, spanToCompress) &&
compositeSpan.name === spanToCompress.name &&
spanToCompress._duration <= (this._agent._conf.spanCompressionExactMatchMaxDuration * 1000)
case STRATEGY_SAME_KIND:
return this.isSameKind(compositeSpan, spanToCompress) &&
spanToCompress._duration <= (this._agent._conf.spanCompressionSameKindMaxDuration * 1000)
}
}
_spanNameFromCompositeSpan (compositeSpan) {
const prefix = 'Calls to '
const serviceTarget = compositeSpan._serviceTarget
if (!serviceTarget.type) {
if (!serviceTarget.name) {
return prefix + 'unknown'
} else {
return prefix + serviceTarget.name
}
} else if (!serviceTarget.name) {
return prefix + serviceTarget.type
} else {
return prefix + serviceTarget.type + '/' + serviceTarget.name
}
}
_isEnabled () {
return this._agent._conf.spanCompressionEnabled
}
isCompositeSameKind () {
return this.composite.compression_strategy === STRATEGY_SAME_KIND
}
isComposite () {
return this.composite.count > 1
}
// Encodes/Serializes composite span properties
// @return Object
encode () {
return {
compression_strategy: this.composite.compression_strategy,
count: this.composite.count,
sum: this.composite.sum
}
}
}
module.exports = {
SpanCompression,
constants: {
STRATEGY_EXACT_MATCH,
STRATEGY_SAME_KIND
}
}