@depup/elastic-apm-node 4.15.0-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +26 -0
- package/NOTICE.md +442 -0
- package/README.md +48 -0
- package/changes.json +78 -0
- package/index.d.ts +398 -0
- package/index.js +11 -0
- package/lib/InflightEventSet.js +53 -0
- package/lib/activation-method.js +119 -0
- package/lib/agent.js +941 -0
- package/lib/apm-client/apm-client.js +313 -0
- package/lib/apm-client/http-apm-client/CHANGELOG.md +271 -0
- package/lib/apm-client/http-apm-client/README.md +485 -0
- package/lib/apm-client/http-apm-client/central-config.js +41 -0
- package/lib/apm-client/http-apm-client/container-info.js +111 -0
- package/lib/apm-client/http-apm-client/detect-hostname.js +96 -0
- package/lib/apm-client/http-apm-client/index.js +1975 -0
- package/lib/apm-client/http-apm-client/logging.js +31 -0
- package/lib/apm-client/http-apm-client/ndjson.js +20 -0
- package/lib/apm-client/http-apm-client/truncate.js +434 -0
- package/lib/apm-client/noop-apm-client.js +73 -0
- package/lib/async-hooks-polyfill.js +58 -0
- package/lib/cloud-metadata/aws.js +175 -0
- package/lib/cloud-metadata/azure.js +123 -0
- package/lib/cloud-metadata/callback-coordination.js +159 -0
- package/lib/cloud-metadata/gcp.js +133 -0
- package/lib/cloud-metadata/index.js +175 -0
- package/lib/config/config.js +458 -0
- package/lib/config/normalizers.js +701 -0
- package/lib/config/schema.js +1007 -0
- package/lib/constants.js +35 -0
- package/lib/errors.js +303 -0
- package/lib/filters/sanitize-field-names.js +69 -0
- package/lib/http-request.js +249 -0
- package/lib/instrumentation/azure-functions.js +519 -0
- package/lib/instrumentation/context.js +56 -0
- package/lib/instrumentation/dropped-spans-stats.js +112 -0
- package/lib/instrumentation/elasticsearch-shared.js +63 -0
- package/lib/instrumentation/express-utils.js +91 -0
- package/lib/instrumentation/generic-span.js +322 -0
- package/lib/instrumentation/http-shared.js +424 -0
- package/lib/instrumentation/ids.js +39 -0
- package/lib/instrumentation/index.js +1127 -0
- package/lib/instrumentation/modules/@apollo/server.js +30 -0
- package/lib/instrumentation/modules/@aws-sdk/client-dynamodb.js +143 -0
- package/lib/instrumentation/modules/@aws-sdk/client-s3.js +230 -0
- package/lib/instrumentation/modules/@aws-sdk/client-sns.js +197 -0
- package/lib/instrumentation/modules/@aws-sdk/client-sqs.js +336 -0
- package/lib/instrumentation/modules/@elastic/elasticsearch.js +343 -0
- package/lib/instrumentation/modules/@hapi/hapi.js +221 -0
- package/lib/instrumentation/modules/@opentelemetry/api.js +86 -0
- package/lib/instrumentation/modules/@opentelemetry/sdk-metrics.js +79 -0
- package/lib/instrumentation/modules/@redis/client/dist/lib/client/commands-queue.js +178 -0
- package/lib/instrumentation/modules/@redis/client/dist/lib/client/index.js +49 -0
- package/lib/instrumentation/modules/@smithy/smithy-client.js +198 -0
- package/lib/instrumentation/modules/_lambda-handler.js +40 -0
- package/lib/instrumentation/modules/apollo-server-core.js +49 -0
- package/lib/instrumentation/modules/aws-sdk/dynamodb.js +155 -0
- package/lib/instrumentation/modules/aws-sdk/s3.js +184 -0
- package/lib/instrumentation/modules/aws-sdk/sns.js +232 -0
- package/lib/instrumentation/modules/aws-sdk/sqs.js +361 -0
- package/lib/instrumentation/modules/aws-sdk.js +76 -0
- package/lib/instrumentation/modules/bluebird.js +93 -0
- package/lib/instrumentation/modules/cassandra-driver.js +280 -0
- package/lib/instrumentation/modules/elasticsearch.js +191 -0
- package/lib/instrumentation/modules/express-graphql.js +66 -0
- package/lib/instrumentation/modules/express-queue.js +28 -0
- package/lib/instrumentation/modules/express.js +162 -0
- package/lib/instrumentation/modules/fastify.js +172 -0
- package/lib/instrumentation/modules/finalhandler.js +41 -0
- package/lib/instrumentation/modules/generic-pool.js +85 -0
- package/lib/instrumentation/modules/graphql.js +256 -0
- package/lib/instrumentation/modules/handlebars.js +22 -0
- package/lib/instrumentation/modules/http.js +112 -0
- package/lib/instrumentation/modules/http2.js +320 -0
- package/lib/instrumentation/modules/https.js +68 -0
- package/lib/instrumentation/modules/ioredis.js +94 -0
- package/lib/instrumentation/modules/jade.js +18 -0
- package/lib/instrumentation/modules/kafkajs.js +476 -0
- package/lib/instrumentation/modules/knex.js +91 -0
- package/lib/instrumentation/modules/koa-router.js +74 -0
- package/lib/instrumentation/modules/koa.js +15 -0
- package/lib/instrumentation/modules/memcached.js +99 -0
- package/lib/instrumentation/modules/mimic-response.js +45 -0
- package/lib/instrumentation/modules/mongodb/lib/cmap/connection_pool.js +40 -0
- package/lib/instrumentation/modules/mongodb-core.js +206 -0
- package/lib/instrumentation/modules/mongodb.js +259 -0
- package/lib/instrumentation/modules/mysql.js +200 -0
- package/lib/instrumentation/modules/mysql2.js +140 -0
- package/lib/instrumentation/modules/pg.js +148 -0
- package/lib/instrumentation/modules/pug.js +18 -0
- package/lib/instrumentation/modules/redis.js +176 -0
- package/lib/instrumentation/modules/restify.js +52 -0
- package/lib/instrumentation/modules/tedious.js +159 -0
- package/lib/instrumentation/modules/undici.js +270 -0
- package/lib/instrumentation/modules/ws.js +59 -0
- package/lib/instrumentation/noop-transaction.js +81 -0
- package/lib/instrumentation/run-context/AbstractRunContextManager.js +215 -0
- package/lib/instrumentation/run-context/AsyncHooksRunContextManager.js +106 -0
- package/lib/instrumentation/run-context/AsyncLocalStorageRunContextManager.js +73 -0
- package/lib/instrumentation/run-context/BasicRunContextManager.js +82 -0
- package/lib/instrumentation/run-context/RunContext.js +151 -0
- package/lib/instrumentation/run-context/index.js +23 -0
- package/lib/instrumentation/shimmer.js +123 -0
- package/lib/instrumentation/span-compression.js +239 -0
- package/lib/instrumentation/span.js +621 -0
- package/lib/instrumentation/template-shared.js +43 -0
- package/lib/instrumentation/timer.js +84 -0
- package/lib/instrumentation/transaction.js +571 -0
- package/lib/lambda.js +992 -0
- package/lib/load-source-map.js +100 -0
- package/lib/logging.js +212 -0
- package/lib/metrics/index.js +92 -0
- package/lib/metrics/platforms/generic/index.js +40 -0
- package/lib/metrics/platforms/generic/process-cpu.js +22 -0
- package/lib/metrics/platforms/generic/process-top.js +157 -0
- package/lib/metrics/platforms/generic/stats.js +34 -0
- package/lib/metrics/platforms/generic/system-cpu.js +51 -0
- package/lib/metrics/platforms/linux/index.js +19 -0
- package/lib/metrics/platforms/linux/stats.js +213 -0
- package/lib/metrics/queue.js +90 -0
- package/lib/metrics/registry.js +52 -0
- package/lib/metrics/reporter.js +119 -0
- package/lib/metrics/runtime.js +77 -0
- package/lib/middleware/connect.js +16 -0
- package/lib/opentelemetry-bridge/OTelBridgeNonRecordingSpan.js +150 -0
- package/lib/opentelemetry-bridge/OTelBridgeRunContext.js +124 -0
- package/lib/opentelemetry-bridge/OTelContextManager.js +82 -0
- package/lib/opentelemetry-bridge/OTelSpan.js +344 -0
- package/lib/opentelemetry-bridge/OTelTracer.js +201 -0
- package/lib/opentelemetry-bridge/OTelTracerProvider.js +25 -0
- package/lib/opentelemetry-bridge/README.md +244 -0
- package/lib/opentelemetry-bridge/index.js +15 -0
- package/lib/opentelemetry-bridge/oblog.js +23 -0
- package/lib/opentelemetry-bridge/opentelemetry-core-mini/README.md +3 -0
- package/lib/opentelemetry-bridge/opentelemetry-core-mini/internal/validators.js +52 -0
- package/lib/opentelemetry-bridge/opentelemetry-core-mini/trace/TraceState.js +109 -0
- package/lib/opentelemetry-bridge/otelutils.js +99 -0
- package/lib/opentelemetry-bridge/setup.js +76 -0
- package/lib/opentelemetry-metrics/ElasticApmMetricExporter.js +285 -0
- package/lib/opentelemetry-metrics/index.js +50 -0
- package/lib/parsers.js +225 -0
- package/lib/propwrap.js +147 -0
- package/lib/stacktraces.js +537 -0
- package/lib/symbols.js +15 -0
- package/lib/tracecontext/index.js +118 -0
- package/lib/tracecontext/traceparent.js +185 -0
- package/lib/tracecontext/tracestate.js +388 -0
- package/lib/wildcard-matcher.js +52 -0
- package/loader.mjs +7 -0
- package/package.json +299 -0
- package/start.d.ts +8 -0
- package/start.js +29 -0
- package/types/aws-lambda.d.ts +98 -0
- package/types/connect.d.ts +23 -0
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and other contributors where applicable.
|
|
3
|
+
* Licensed under the BSD 2-Clause License; you may not use this file except in
|
|
4
|
+
* compliance with the BSD 2-Clause License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const { randomFillSync } = require('crypto');
|
|
10
|
+
|
|
11
|
+
const SIZES = {
|
|
12
|
+
version: 1,
|
|
13
|
+
traceId: 16,
|
|
14
|
+
id: 8,
|
|
15
|
+
flags: 1,
|
|
16
|
+
parentId: 8,
|
|
17
|
+
|
|
18
|
+
// Aggregate sizes
|
|
19
|
+
ids: 24, // traceId + id
|
|
20
|
+
all: 34,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const OFFSETS = {
|
|
24
|
+
version: 0,
|
|
25
|
+
traceId: SIZES.version,
|
|
26
|
+
id: SIZES.version + SIZES.traceId,
|
|
27
|
+
flags: SIZES.version + SIZES.ids,
|
|
28
|
+
|
|
29
|
+
// Additional parentId is stored after the header content
|
|
30
|
+
parentId: SIZES.version + SIZES.ids + SIZES.flags,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const FLAGS = {
|
|
34
|
+
recorded: 0b00000001,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
function defineLazyProp(obj, prop, fn) {
|
|
38
|
+
Object.defineProperty(obj, prop, {
|
|
39
|
+
configurable: true,
|
|
40
|
+
enumerable: true,
|
|
41
|
+
get() {
|
|
42
|
+
const value = fn();
|
|
43
|
+
if (value !== undefined) {
|
|
44
|
+
Object.defineProperty(obj, prop, {
|
|
45
|
+
configurable: true,
|
|
46
|
+
enumerable: true,
|
|
47
|
+
value,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return value;
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function hexSliceFn(buffer, offset, length) {
|
|
56
|
+
return () => buffer.slice(offset, length).toString('hex');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function maybeHexSliceFn(buffer, offset, length) {
|
|
60
|
+
const fn = hexSliceFn(buffer, offset, length);
|
|
61
|
+
return () => {
|
|
62
|
+
const value = fn();
|
|
63
|
+
// Check for any non-zero characters to identify a valid ID
|
|
64
|
+
if (/[1-9a-f]/.test(value)) {
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function makeChild(buffer) {
|
|
71
|
+
// Move current id into parentId region
|
|
72
|
+
buffer.copy(buffer, OFFSETS.parentId, OFFSETS.id, OFFSETS.flags);
|
|
73
|
+
|
|
74
|
+
// Generate new id
|
|
75
|
+
randomFillSync(buffer, OFFSETS.id, SIZES.id);
|
|
76
|
+
|
|
77
|
+
return new TraceParent(buffer);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function isValidHeader(header) {
|
|
81
|
+
return /^[\da-f]{2}-[\da-f]{32}-[\da-f]{16}-[\da-f]{2}$/.test(header);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// NOTE: The version byte is not fully supported yet, but is not important until
|
|
85
|
+
// we use the official header name rather than elastic-apm-traceparent.
|
|
86
|
+
// https://w3c.github.io/distributed-tracing/report-trace-context.html#versioning-of-traceparent
|
|
87
|
+
function headerToBuffer(header) {
|
|
88
|
+
const buffer = Buffer.alloc(SIZES.all);
|
|
89
|
+
buffer.write(header.replace(/-/g, ''), 'hex');
|
|
90
|
+
return buffer;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function resume(header) {
|
|
94
|
+
return makeChild(headerToBuffer(header));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function start(sampled = false) {
|
|
98
|
+
const buffer = Buffer.alloc(SIZES.all);
|
|
99
|
+
|
|
100
|
+
// Generate new ids
|
|
101
|
+
randomFillSync(buffer, OFFSETS.traceId, SIZES.ids);
|
|
102
|
+
|
|
103
|
+
if (sampled) {
|
|
104
|
+
buffer[OFFSETS.flags] |= FLAGS.recorded;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return new TraceParent(buffer);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const bufferSymbol = Symbol('trace-context-buffer');
|
|
111
|
+
|
|
112
|
+
class TraceParent {
|
|
113
|
+
constructor(buffer) {
|
|
114
|
+
this[bufferSymbol] = buffer;
|
|
115
|
+
Object.defineProperty(this, 'recorded', {
|
|
116
|
+
enumerable: true,
|
|
117
|
+
get: function () {
|
|
118
|
+
return !!(this[bufferSymbol][OFFSETS.flags] & FLAGS.recorded);
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
defineLazyProp(
|
|
123
|
+
this,
|
|
124
|
+
'version',
|
|
125
|
+
hexSliceFn(buffer, OFFSETS.version, OFFSETS.traceId),
|
|
126
|
+
);
|
|
127
|
+
defineLazyProp(
|
|
128
|
+
this,
|
|
129
|
+
'traceId',
|
|
130
|
+
hexSliceFn(buffer, OFFSETS.traceId, OFFSETS.id),
|
|
131
|
+
);
|
|
132
|
+
defineLazyProp(this, 'id', hexSliceFn(buffer, OFFSETS.id, OFFSETS.flags));
|
|
133
|
+
defineLazyProp(
|
|
134
|
+
this,
|
|
135
|
+
'flags',
|
|
136
|
+
hexSliceFn(buffer, OFFSETS.flags, OFFSETS.parentId),
|
|
137
|
+
);
|
|
138
|
+
defineLazyProp(this, 'parentId', maybeHexSliceFn(buffer, OFFSETS.parentId));
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
static startOrResume(childOf, conf) {
|
|
142
|
+
if (childOf instanceof TraceParent) return childOf.child();
|
|
143
|
+
if (childOf && childOf._context instanceof TraceParent)
|
|
144
|
+
return childOf._context.child();
|
|
145
|
+
|
|
146
|
+
return isValidHeader(childOf)
|
|
147
|
+
? resume(childOf)
|
|
148
|
+
: start(Math.random() <= conf.transactionSampleRate);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
static fromString(header) {
|
|
152
|
+
return new TraceParent(headerToBuffer(header));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
ensureParentId() {
|
|
156
|
+
let id = this.parentId;
|
|
157
|
+
if (!id) {
|
|
158
|
+
randomFillSync(this[bufferSymbol], OFFSETS.parentId, SIZES.id);
|
|
159
|
+
id = this.parentId;
|
|
160
|
+
}
|
|
161
|
+
return id;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
child() {
|
|
165
|
+
return makeChild(Buffer.from(this[bufferSymbol]));
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
setRecorded(value) {
|
|
169
|
+
if (value) {
|
|
170
|
+
this[bufferSymbol][OFFSETS.flags] |= FLAGS.recorded;
|
|
171
|
+
} else {
|
|
172
|
+
this[bufferSymbol][OFFSETS.flags] &= ~FLAGS.recorded;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
toString() {
|
|
177
|
+
return `${this.version}-${this.traceId}-${this.id}-${this.flags}`;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
TraceParent.FLAGS = FLAGS;
|
|
182
|
+
|
|
183
|
+
module.exports = {
|
|
184
|
+
TraceParent,
|
|
185
|
+
};
|
|
@@ -0,0 +1,388 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and other contributors where applicable.
|
|
3
|
+
* Licensed under the BSD 2-Clause License; you may not use this file except in
|
|
4
|
+
* compliance with the BSD 2-Clause License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
// Indirect usage of the singleton `Agent` to log.
|
|
10
|
+
function getLogger() {
|
|
11
|
+
return require('../..').logger;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Class for Managing Tracestate
|
|
16
|
+
*
|
|
17
|
+
* Class that creates objects for managing trace state.
|
|
18
|
+
* This class is capable of parsing both tracestate strings
|
|
19
|
+
* and tracestate binary representations, allowing clients
|
|
20
|
+
* to get and set values in a single list-member/namespace
|
|
21
|
+
* while preserving values in the other namespaces.
|
|
22
|
+
*
|
|
23
|
+
* Capable of working with either the binary of string
|
|
24
|
+
* formatted tracestate values.
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
* const tracestate = TraceState.fromStringFormatString(headerTracestate, 'es')
|
|
28
|
+
* tracestate.setValue('s',1)
|
|
29
|
+
* const newHeader = tracestate.toW3cString()
|
|
30
|
+
*/
|
|
31
|
+
class TraceState {
|
|
32
|
+
constructor(sourceBuffer, listMemberNamespace = 'es', defaultValues = {}) {
|
|
33
|
+
if (!this._validateVendorKey(listMemberNamespace)) {
|
|
34
|
+
throw new Error('Vendor namespace failed validation.');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// buffer representation of the trace state string.
|
|
38
|
+
// The initial value of this.buffer will keep the
|
|
39
|
+
// values set in the listMemberNamespace list-member,
|
|
40
|
+
// but as soon as an initial value is set (via setValue)
|
|
41
|
+
// then the listMemberNamespace values will be removed
|
|
42
|
+
// from this.buffer and stored in the this.values. While
|
|
43
|
+
// slightly more complicated, this allows us to maintain
|
|
44
|
+
// the order of list-member keys in an un-mutated tracestate
|
|
45
|
+
// string, per the W3C spec
|
|
46
|
+
this.buffer = sourceBuffer;
|
|
47
|
+
|
|
48
|
+
this.listMemberNamespace = listMemberNamespace;
|
|
49
|
+
|
|
50
|
+
// values for our namespace, set via setValue to
|
|
51
|
+
// ensure names conform
|
|
52
|
+
this.values = {};
|
|
53
|
+
for (const key in defaultValues) {
|
|
54
|
+
const value = defaultValues[key];
|
|
55
|
+
this.setValue(key, value);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
setValue(key, value) {
|
|
60
|
+
const strKey = String(key);
|
|
61
|
+
const strValue = String(value);
|
|
62
|
+
if (!this._validateElasicKeyAndValue(strKey, strValue)) {
|
|
63
|
+
getLogger().trace(
|
|
64
|
+
'could not set tracestate key, invalid characters detected',
|
|
65
|
+
);
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
const isFirstSet = Object.keys(this.values).length === 0;
|
|
69
|
+
const oldValue = this.values[strKey];
|
|
70
|
+
this.values[strKey] = value;
|
|
71
|
+
|
|
72
|
+
// per: https://github.com/elastic/apm/blob/d5b2c87326548befcfec6731713932a00e430b99/specs/agents/tracing-distributed-tracing.md
|
|
73
|
+
// If adding another key/value pair to the es entry would exceed the limit
|
|
74
|
+
// of 256 chars, that key/value pair MUST be ignored by agents.
|
|
75
|
+
// The key/value and entry separators : and ; have to be considered as well.
|
|
76
|
+
const serializedValue = this._serializeValues(this.values);
|
|
77
|
+
if (serializedValue.length > 256 && typeof oldValue === 'undefined') {
|
|
78
|
+
delete this.values[strKey];
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
if (serializedValue.length > 256 && typeof oldValue !== 'undefined') {
|
|
82
|
+
this.values[strKey] = oldValue;
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// the first time we set a value, extract the mutable values from the
|
|
87
|
+
// buffer and set this.values appropriately
|
|
88
|
+
if (isFirstSet && Object.keys(this.values).length === 1) {
|
|
89
|
+
const [buffer, values] = TraceState._removeMemberNamespaceFromBuffer(
|
|
90
|
+
this.buffer,
|
|
91
|
+
this.listMemberNamespace,
|
|
92
|
+
);
|
|
93
|
+
this.buffer = buffer;
|
|
94
|
+
this.values = values;
|
|
95
|
+
values[strKey] = value;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
getValue(keyToGet) {
|
|
102
|
+
const allValues = this.toObject();
|
|
103
|
+
const rawValue = allValues[this.listMemberNamespace];
|
|
104
|
+
if (!rawValue) {
|
|
105
|
+
return rawValue;
|
|
106
|
+
}
|
|
107
|
+
const values = TraceState._parseValues(rawValue);
|
|
108
|
+
return values[keyToGet];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
toHexString() {
|
|
112
|
+
const newBuffer = Buffer.alloc(this.buffer.length);
|
|
113
|
+
let newBufferOffset = 0;
|
|
114
|
+
for (let i = 0; i < this.buffer.length; i++) {
|
|
115
|
+
const byte = this.buffer[i];
|
|
116
|
+
if (byte === 0) {
|
|
117
|
+
const indexOfKeyLength = i + 1;
|
|
118
|
+
const indexOfKey = i + 2;
|
|
119
|
+
const lengthKey = this.buffer[indexOfKeyLength];
|
|
120
|
+
|
|
121
|
+
const indexOfValueLength = indexOfKey + lengthKey;
|
|
122
|
+
const indexOfValue = indexOfValueLength + 1;
|
|
123
|
+
const lengthValue = this.buffer[indexOfValueLength];
|
|
124
|
+
|
|
125
|
+
const key = this.buffer
|
|
126
|
+
.slice(indexOfKey, indexOfKey + lengthKey)
|
|
127
|
+
.toString();
|
|
128
|
+
// bail out if this is our mutable namespace
|
|
129
|
+
if (key === this.listMemberNamespace) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// if this is not our key copy from the `0` byte to the end of the value
|
|
134
|
+
this.buffer.copy(
|
|
135
|
+
newBuffer,
|
|
136
|
+
newBufferOffset,
|
|
137
|
+
i,
|
|
138
|
+
indexOfValue + lengthValue,
|
|
139
|
+
);
|
|
140
|
+
newBufferOffset += indexOfValue + lengthValue;
|
|
141
|
+
|
|
142
|
+
// skip ahead to first byte after end of value
|
|
143
|
+
i = indexOfValue + lengthValue - 1;
|
|
144
|
+
continue;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// now serialize the internal representation
|
|
149
|
+
const ourBytes = [];
|
|
150
|
+
if (Object.keys(this.values).length > 0) {
|
|
151
|
+
// the zero byte
|
|
152
|
+
ourBytes.push(0);
|
|
153
|
+
|
|
154
|
+
// the length of the vendor namespace
|
|
155
|
+
ourBytes.push(this.listMemberNamespace.length);
|
|
156
|
+
// the chars of the vendor namespace
|
|
157
|
+
for (let i = 0; i < this.listMemberNamespace.length; i++) {
|
|
158
|
+
ourBytes.push(this.listMemberNamespace.charCodeAt(i));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// add the length of the value
|
|
162
|
+
const serializedValue = this._serializeValues(this.values);
|
|
163
|
+
ourBytes.push(serializedValue.length);
|
|
164
|
+
|
|
165
|
+
// add the bytes of the value
|
|
166
|
+
for (let i = 0; i < serializedValue.length; i++) {
|
|
167
|
+
ourBytes.push(serializedValue.charCodeAt(i));
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
const ourBuffer = Buffer.from(ourBytes);
|
|
171
|
+
return Buffer.concat(
|
|
172
|
+
[newBuffer, ourBuffer],
|
|
173
|
+
newBuffer.length + ourBuffer.length,
|
|
174
|
+
).toString('hex');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Returns JSON reprenstation of tracestate key/value pairs
|
|
179
|
+
*
|
|
180
|
+
* Does not parse the mutable list namespace
|
|
181
|
+
*/
|
|
182
|
+
toObject() {
|
|
183
|
+
const map = this.toMap();
|
|
184
|
+
const obj = {};
|
|
185
|
+
for (const key of map.keys()) {
|
|
186
|
+
obj[key] = map.get(key);
|
|
187
|
+
}
|
|
188
|
+
return obj;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
toMap() {
|
|
192
|
+
const map = new Map();
|
|
193
|
+
|
|
194
|
+
// first, serialize values from the internal representation. This means
|
|
195
|
+
// The W3C spec dictates that mutated values need to be on
|
|
196
|
+
// the left of the new trace string
|
|
197
|
+
if (Object.keys(this.values).length) {
|
|
198
|
+
map.set(this.listMemberNamespace, this._serializeValues(this.values));
|
|
199
|
+
}
|
|
200
|
+
for (let i = 0; i < this.buffer.length; i++) {
|
|
201
|
+
const byte = this.buffer[i];
|
|
202
|
+
if (byte === 0) {
|
|
203
|
+
const indexOfKeyLength = i + 1;
|
|
204
|
+
const indexOfKey = i + 2;
|
|
205
|
+
const lengthKey = this.buffer[indexOfKeyLength];
|
|
206
|
+
|
|
207
|
+
const indexOfValueLength = indexOfKey + lengthKey;
|
|
208
|
+
const indexOfValue = indexOfValueLength + 1;
|
|
209
|
+
const lengthValue = this.buffer[indexOfValueLength];
|
|
210
|
+
|
|
211
|
+
const key = this.buffer
|
|
212
|
+
.slice(indexOfKey, indexOfKey + lengthKey)
|
|
213
|
+
.toString();
|
|
214
|
+
const value = this.buffer
|
|
215
|
+
.slice(indexOfValue, indexOfValue + lengthValue)
|
|
216
|
+
.toString();
|
|
217
|
+
|
|
218
|
+
map.set(key, value);
|
|
219
|
+
|
|
220
|
+
// skip ahead
|
|
221
|
+
i = indexOfValue + lengthValue - 1;
|
|
222
|
+
continue;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return map;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
toString() {
|
|
230
|
+
return this.toW3cString();
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
toW3cString() {
|
|
234
|
+
const json = this.toObject();
|
|
235
|
+
const chars = [];
|
|
236
|
+
for (const key in json) {
|
|
237
|
+
const value = json[key];
|
|
238
|
+
if (!value) {
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
chars.push(key);
|
|
242
|
+
chars.push('=');
|
|
243
|
+
chars.push(value);
|
|
244
|
+
chars.push(',');
|
|
245
|
+
}
|
|
246
|
+
chars.pop(); // remove final comma
|
|
247
|
+
return chars.join('');
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
_serializeValues(keyValues) {
|
|
251
|
+
const chars = [];
|
|
252
|
+
for (const key in keyValues) {
|
|
253
|
+
const value = keyValues[key];
|
|
254
|
+
chars.push(`${key}:${value}`);
|
|
255
|
+
chars.push(';');
|
|
256
|
+
}
|
|
257
|
+
chars.pop(); // last semi-colon
|
|
258
|
+
return chars.join('');
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
_validateVendorKey(key) {
|
|
262
|
+
if (key.length > 256 || key.length < 1) {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
const re = /^[abcdefghijklmnopqrstuvwxyz0123456789_\-*/]*$/;
|
|
266
|
+
if (!key.match(re)) {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
_validateElasicKeyAndValue(key, value) {
|
|
273
|
+
// 0x20` to `0x7E WITHOUT `,` or `=` or `;` or `;`
|
|
274
|
+
const re =
|
|
275
|
+
/^[ \][!"#$%&'()*+\-./0123456789<>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_abcdefghijklmnopqrstuvwxyz{|}~]*$/;
|
|
276
|
+
|
|
277
|
+
if (!key.match(re) || !value.match(re)) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (key.length > 256 || value.length > 256) {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
static fromBinaryFormatHexString(string, listMemberNamespace = 'es') {
|
|
289
|
+
return new TraceState(Buffer.from(string, 'hex'), listMemberNamespace);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
static fromStringFormatString(string = '', listMemberNamespace = 'es') {
|
|
293
|
+
// converts string format to byte format
|
|
294
|
+
const bytes = [];
|
|
295
|
+
|
|
296
|
+
const parts = string.split(',');
|
|
297
|
+
for (let part of parts) {
|
|
298
|
+
part = part.trim(); // optional whitespace (OWS)
|
|
299
|
+
if (!part) {
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
const [listMember, value] = part.split('=');
|
|
303
|
+
if (!listMember || !value) {
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
bytes.push(0);
|
|
307
|
+
bytes.push(listMember.length);
|
|
308
|
+
for (let i = 0; i < listMember.length; i++) {
|
|
309
|
+
bytes.push(listMember.charCodeAt(i));
|
|
310
|
+
}
|
|
311
|
+
bytes.push(value.length);
|
|
312
|
+
for (let i = 0; i < value.length; i++) {
|
|
313
|
+
bytes.push(value.charCodeAt(i));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
return new TraceState(Buffer.from(bytes), listMemberNamespace);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
static _parseValues(rawValues) {
|
|
321
|
+
const parsedValues = {};
|
|
322
|
+
const parts = rawValues.split(';');
|
|
323
|
+
for (const keyValue of parts) {
|
|
324
|
+
if (!keyValue) {
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
const [key, value] = keyValue.split(':');
|
|
328
|
+
if (!key || !value) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
parsedValues[key] = value;
|
|
332
|
+
}
|
|
333
|
+
return parsedValues;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
static _removeMemberNamespaceFromBuffer(buffer, listMemberNamespace) {
|
|
337
|
+
const newBuffer = Buffer.alloc(buffer.length);
|
|
338
|
+
let newBufferOffset = 0;
|
|
339
|
+
const values = {};
|
|
340
|
+
for (let i = 0; i < buffer.length; i++) {
|
|
341
|
+
const byte = buffer[i];
|
|
342
|
+
if (byte === 0) {
|
|
343
|
+
const indexOfKeyLength = i + 1;
|
|
344
|
+
const indexOfKey = i + 2;
|
|
345
|
+
const lengthKey = buffer[indexOfKeyLength];
|
|
346
|
+
|
|
347
|
+
const indexOfValueLength = indexOfKey + lengthKey;
|
|
348
|
+
const indexOfValue = indexOfValueLength + 1;
|
|
349
|
+
const lengthValue = buffer[indexOfValueLength];
|
|
350
|
+
|
|
351
|
+
const key = buffer.slice(indexOfKey, indexOfKey + lengthKey).toString();
|
|
352
|
+
|
|
353
|
+
// if this is our mutable namespace extract
|
|
354
|
+
// and set the value in values, otherwise
|
|
355
|
+
// copy into new buffer
|
|
356
|
+
if (key === listMemberNamespace) {
|
|
357
|
+
const rawValues = buffer
|
|
358
|
+
.slice(indexOfValue, indexOfValue + lengthValue)
|
|
359
|
+
.toString();
|
|
360
|
+
const parsedValues = TraceState._parseValues(rawValues);
|
|
361
|
+
for (const key in parsedValues) {
|
|
362
|
+
values[key] = parsedValues[key];
|
|
363
|
+
}
|
|
364
|
+
continue;
|
|
365
|
+
} else {
|
|
366
|
+
buffer.copy(
|
|
367
|
+
newBuffer,
|
|
368
|
+
newBufferOffset,
|
|
369
|
+
i,
|
|
370
|
+
indexOfValue + lengthValue,
|
|
371
|
+
);
|
|
372
|
+
newBufferOffset += indexOfValue + lengthValue - i;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// skip ahead to first byte after end of value
|
|
376
|
+
i = indexOfValue + lengthValue - 1;
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// trim off extra 0 bytes
|
|
382
|
+
const trimmedBuffer = newBuffer.slice(0, newBufferOffset);
|
|
383
|
+
|
|
384
|
+
return [trimmedBuffer, values];
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
module.exports = TraceState;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright Elasticsearch B.V. and other contributors where applicable.
|
|
3
|
+
* Licensed under the BSD 2-Clause License; you may not use this file except in
|
|
4
|
+
* compliance with the BSD 2-Clause License.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
/**
|
|
9
|
+
* Implements a Wildcard matcher
|
|
10
|
+
*
|
|
11
|
+
* Exports a function that implements a simple wildcard matcher
|
|
12
|
+
* per: https://github.com/elastic/apm/issues/144
|
|
13
|
+
*/
|
|
14
|
+
const escapeStringRegexp = require('escape-string-regexp');
|
|
15
|
+
|
|
16
|
+
// Converts elastic-wildcard pattern into a
|
|
17
|
+
// a javascript regular expression.
|
|
18
|
+
const starMatchToRegex = (pattern) => {
|
|
19
|
+
// case insensative by default
|
|
20
|
+
let regexOpts = ['i'];
|
|
21
|
+
if (pattern.startsWith('(?-i)')) {
|
|
22
|
+
regexOpts = [];
|
|
23
|
+
pattern = pattern.slice(5);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const patternLength = pattern.length;
|
|
27
|
+
const reChars = ['^'];
|
|
28
|
+
for (let i = 0; i < patternLength; i++) {
|
|
29
|
+
const char = pattern[i];
|
|
30
|
+
switch (char) {
|
|
31
|
+
case '*':
|
|
32
|
+
reChars.push('.*');
|
|
33
|
+
break;
|
|
34
|
+
default:
|
|
35
|
+
reChars.push(escapeStringRegexp(char));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
reChars.push('$');
|
|
39
|
+
return new RegExp(reChars.join(''), regexOpts.join(''));
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
class WildcardMatcher {
|
|
43
|
+
compile(pattern) {
|
|
44
|
+
return starMatchToRegex(pattern);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
match(string, pattern) {
|
|
48
|
+
const re = this.compile(pattern);
|
|
49
|
+
return string.search(re) !== -1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
module.exports = { WildcardMatcher };
|
package/loader.mjs
ADDED