dd-trace 5.40.0 → 5.41.1
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-3rdparty.csv +1 -0
- package/package.json +4 -3
- package/packages/datadog-instrumentations/src/fetch.js +1 -1
- package/packages/datadog-plugin-graphql/src/parse.js +1 -3
- package/packages/datadog-plugin-mongodb-core/src/index.js +4 -1
- package/packages/dd-trace/src/config.js +112 -18
- package/packages/dd-trace/src/config_stable.js +100 -0
- package/packages/dd-trace/src/dogstatsd.js +137 -28
- package/packages/dd-trace/src/format.js +0 -1
- package/packages/dd-trace/src/llmobs/plugins/base.js +3 -0
- package/packages/dd-trace/src/llmobs/plugins/bedrockruntime.js +3 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +1 -0
- package/packages/dd-trace/src/llmobs/plugins/openai.js +1 -0
- package/packages/dd-trace/src/llmobs/sdk.js +5 -0
- package/packages/dd-trace/src/llmobs/telemetry.js +12 -0
- package/packages/dd-trace/src/log/index.js +26 -13
- package/packages/dd-trace/src/plugin_manager.js +0 -4
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/util/git.js +22 -10
- package/packages/dd-trace/src/plugins/util/web.js +3 -2
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +15 -80
- package/packages/dd-trace/src/tagger.js +7 -14
- package/packages/dd-trace/src/util.js +10 -1
package/LICENSE-3rdparty.csv
CHANGED
|
@@ -37,6 +37,7 @@ dev,@eslint/eslintrc,MIT,Copyright OpenJS Foundation and other contributors, <ww
|
|
|
37
37
|
dev,@eslint/js,MIT,Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
|
|
38
38
|
dev,@msgpack/msgpack,ISC,Copyright 2019 The MessagePack Community
|
|
39
39
|
dev,@stylistic/eslint-plugin-js,MIT,Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
|
|
40
|
+
dev,application-config-path,MIT,Copyright (c) 2015, 2023 Linus Unnebäck
|
|
40
41
|
dev,autocannon,MIT,Copyright 2016 Matteo Collina
|
|
41
42
|
dev,aws-sdk,Apache 2.0,Copyright 2012-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
42
43
|
dev,axios,MIT,Copyright 2014-present Matt Zabriskie
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.41.1",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
"node": ">=18"
|
|
83
83
|
},
|
|
84
84
|
"dependencies": {
|
|
85
|
-
"@datadog/libdatadog": "^0.
|
|
85
|
+
"@datadog/libdatadog": "^0.5.0",
|
|
86
86
|
"@datadog/native-appsec": "8.4.0",
|
|
87
87
|
"@datadog/native-iast-rewriter": "2.8.0",
|
|
88
88
|
"@datadog/native-iast-taint-tracking": "3.3.0",
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"crypto-randomuuid": "^1.0.0",
|
|
96
96
|
"dc-polyfill": "^0.1.4",
|
|
97
97
|
"ignore": "^5.2.4",
|
|
98
|
-
"import-in-the-middle": "1.
|
|
98
|
+
"import-in-the-middle": "1.13.1",
|
|
99
99
|
"istanbul-lib-coverage": "3.2.0",
|
|
100
100
|
"jest-docblock": "^29.7.0",
|
|
101
101
|
"koalas": "^1.0.2",
|
|
@@ -122,6 +122,7 @@
|
|
|
122
122
|
"@msgpack/msgpack": "^3.0.0-beta3",
|
|
123
123
|
"@stylistic/eslint-plugin-js": "^3.0.1",
|
|
124
124
|
"@types/node": "^16.0.0",
|
|
125
|
+
"application-config-path": "^1.0.0",
|
|
125
126
|
"autocannon": "^4.5.2",
|
|
126
127
|
"aws-sdk": "^2.1446.0",
|
|
127
128
|
"axios": "^1.7.4",
|
|
@@ -17,7 +17,7 @@ if (globalThis.fetch) {
|
|
|
17
17
|
|
|
18
18
|
const ch = tracingChannel('apm:fetch:request')
|
|
19
19
|
const wrapFetch = createWrapFetch(globalThis.Request, ch, () => {
|
|
20
|
-
channel('dd-trace:instrumentation:load').publish({ name: 'fetch' })
|
|
20
|
+
channel('dd-trace:instrumentation:load').publish({ name: 'global:fetch' })
|
|
21
21
|
})
|
|
22
22
|
|
|
23
23
|
fetch = wrapFetch(globalFetch)
|
|
@@ -25,7 +25,10 @@ class MongodbCorePlugin extends DatabasePlugin {
|
|
|
25
25
|
'out.port': options.port
|
|
26
26
|
}
|
|
27
27
|
})
|
|
28
|
-
|
|
28
|
+
const comment = this.injectDbmComment(span, ops.comment, service)
|
|
29
|
+
if (comment) {
|
|
30
|
+
ops.comment = comment
|
|
31
|
+
}
|
|
29
32
|
}
|
|
30
33
|
|
|
31
34
|
getPeerService (tags) {
|
|
@@ -11,7 +11,7 @@ const tagger = require('./tagger')
|
|
|
11
11
|
const get = require('../../datadog-core/src/utils/src/get')
|
|
12
12
|
const has = require('../../datadog-core/src/utils/src/has')
|
|
13
13
|
const set = require('../../datadog-core/src/utils/src/set')
|
|
14
|
-
const { isTrue, isFalse } = require('./util')
|
|
14
|
+
const { isTrue, isFalse, normalizeProfilingEnabledValue } = require('./util')
|
|
15
15
|
const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('./plugins/util/tags')
|
|
16
16
|
const { getGitMetadataFromGitProperties, removeUserSensitiveInfo } = require('./git_properties')
|
|
17
17
|
const { updateConfig } = require('./telemetry')
|
|
@@ -236,6 +236,12 @@ function reformatSpanSamplingRules (rules) {
|
|
|
236
236
|
|
|
237
237
|
class Config {
|
|
238
238
|
constructor (options = {}) {
|
|
239
|
+
if (!isInServerlessEnvironment()) {
|
|
240
|
+
// Bail out early if we're in a serverless environment, stable config isn't supported
|
|
241
|
+
const StableConfig = require('./config_stable')
|
|
242
|
+
this.stableConfig = new StableConfig()
|
|
243
|
+
}
|
|
244
|
+
|
|
239
245
|
options = {
|
|
240
246
|
...options,
|
|
241
247
|
appsec: options.appsec != null ? options.appsec : options.experimental?.appsec,
|
|
@@ -244,13 +250,24 @@ class Config {
|
|
|
244
250
|
|
|
245
251
|
// Configure the logger first so it can be used to warn about other configs
|
|
246
252
|
const logConfig = log.getConfig()
|
|
247
|
-
this.debug =
|
|
253
|
+
this.debug = log.isEnabled(
|
|
254
|
+
this.stableConfig?.fleetEntries?.DD_TRACE_DEBUG,
|
|
255
|
+
this.stableConfig?.localEntries?.DD_TRACE_DEBUG
|
|
256
|
+
)
|
|
248
257
|
this.logger = coalesce(options.logger, logConfig.logger)
|
|
249
|
-
this.logLevel =
|
|
250
|
-
|
|
258
|
+
this.logLevel = log.getLogLevel(
|
|
259
|
+
options.logLevel,
|
|
260
|
+
this.stableConfig?.fleetEntries?.DD_TRACE_LOG_LEVEL,
|
|
261
|
+
this.stableConfig?.localEntries?.DD_TRACE_LOG_LEVEL
|
|
262
|
+
)
|
|
251
263
|
log.use(this.logger)
|
|
252
264
|
log.toggle(this.debug, this.logLevel)
|
|
253
265
|
|
|
266
|
+
// Process stable config warnings, if any
|
|
267
|
+
for (const warning of this.stableConfig?.warnings ?? []) {
|
|
268
|
+
log.warn(warning)
|
|
269
|
+
}
|
|
270
|
+
|
|
254
271
|
checkIfBothOtelAndDdEnvVarSet()
|
|
255
272
|
|
|
256
273
|
const DD_API_KEY = coalesce(
|
|
@@ -337,7 +354,9 @@ class Config {
|
|
|
337
354
|
}
|
|
338
355
|
|
|
339
356
|
this._applyDefaults()
|
|
357
|
+
this._applyLocalStableConfig()
|
|
340
358
|
this._applyEnvironment()
|
|
359
|
+
this._applyFleetStableConfig()
|
|
341
360
|
this._applyOptions(options)
|
|
342
361
|
this._applyCalculated()
|
|
343
362
|
this._applyRemote({})
|
|
@@ -576,6 +595,45 @@ class Config {
|
|
|
576
595
|
this._setValue(defaults, 'trace.dynamoDb.tablePrimaryKeys', undefined)
|
|
577
596
|
}
|
|
578
597
|
|
|
598
|
+
_applyLocalStableConfig () {
|
|
599
|
+
const obj = setHiddenProperty(this, '_localStableConfig', {})
|
|
600
|
+
this._applyStableConfig(this.stableConfig?.localEntries ?? {}, obj)
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
_applyFleetStableConfig () {
|
|
604
|
+
const obj = setHiddenProperty(this, '_fleetStableConfig', {})
|
|
605
|
+
this._applyStableConfig(this.stableConfig?.fleetEntries ?? {}, obj)
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
_applyStableConfig (config, obj) {
|
|
609
|
+
const {
|
|
610
|
+
DD_APPSEC_ENABLED,
|
|
611
|
+
DD_APPSEC_SCA_ENABLED,
|
|
612
|
+
DD_DATA_STREAMS_ENABLED,
|
|
613
|
+
DD_DYNAMIC_INSTRUMENTATION_ENABLED,
|
|
614
|
+
DD_ENV,
|
|
615
|
+
DD_IAST_ENABLED,
|
|
616
|
+
DD_LOGS_INJECTION,
|
|
617
|
+
DD_PROFILING_ENABLED,
|
|
618
|
+
DD_RUNTIME_METRICS_ENABLED,
|
|
619
|
+
DD_SERVICE,
|
|
620
|
+
DD_VERSION
|
|
621
|
+
} = config
|
|
622
|
+
|
|
623
|
+
this._setBoolean(obj, 'appsec.enabled', DD_APPSEC_ENABLED)
|
|
624
|
+
this._setBoolean(obj, 'appsec.sca.enabled', DD_APPSEC_SCA_ENABLED)
|
|
625
|
+
this._setBoolean(obj, 'dsmEnabled', DD_DATA_STREAMS_ENABLED)
|
|
626
|
+
this._setBoolean(obj, 'dynamicInstrumentation.enabled', DD_DYNAMIC_INSTRUMENTATION_ENABLED)
|
|
627
|
+
this._setString(obj, 'env', DD_ENV)
|
|
628
|
+
this._setBoolean(obj, 'iast.enabled', DD_IAST_ENABLED)
|
|
629
|
+
this._setBoolean(obj, 'logInjection', DD_LOGS_INJECTION)
|
|
630
|
+
const profilingEnabled = normalizeProfilingEnabledValue(DD_PROFILING_ENABLED)
|
|
631
|
+
this._setString(obj, 'profiling.enabled', profilingEnabled)
|
|
632
|
+
this._setBoolean(obj, 'runtimeMetrics', DD_RUNTIME_METRICS_ENABLED)
|
|
633
|
+
this._setString(obj, 'service', DD_SERVICE)
|
|
634
|
+
this._setString(obj, 'version', DD_VERSION)
|
|
635
|
+
}
|
|
636
|
+
|
|
579
637
|
_applyEnvironment () {
|
|
580
638
|
const {
|
|
581
639
|
AWS_LAMBDA_FUNCTION_NAME,
|
|
@@ -715,8 +773,8 @@ class Config {
|
|
|
715
773
|
const env = setHiddenProperty(this, '_env', {})
|
|
716
774
|
setHiddenProperty(this, '_envUnprocessed', {})
|
|
717
775
|
|
|
718
|
-
tagger.add(tags, OTEL_RESOURCE_ATTRIBUTES
|
|
719
|
-
tagger.add(tags, DD_TAGS)
|
|
776
|
+
tagger.add(tags, parseSpaceSeparatedTags(handleOtel(OTEL_RESOURCE_ATTRIBUTES)))
|
|
777
|
+
tagger.add(tags, parseSpaceSeparatedTags(DD_TAGS))
|
|
720
778
|
tagger.add(tags, DD_TRACE_TAGS)
|
|
721
779
|
tagger.add(tags, DD_TRACE_GLOBAL_TAGS)
|
|
722
780
|
|
|
@@ -831,16 +889,13 @@ class Config {
|
|
|
831
889
|
this._envUnprocessed.peerServiceMapping = DD_TRACE_PEER_SERVICE_MAPPING
|
|
832
890
|
}
|
|
833
891
|
this._setString(env, 'port', DD_TRACE_AGENT_PORT)
|
|
834
|
-
const
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
892
|
+
const profilingEnabled = normalizeProfilingEnabledValue(
|
|
893
|
+
coalesce(
|
|
894
|
+
DD_EXPERIMENTAL_PROFILING_ENABLED,
|
|
895
|
+
DD_PROFILING_ENABLED,
|
|
896
|
+
this._isInServerlessEnvironment() ? 'false' : undefined
|
|
897
|
+
)
|
|
838
898
|
)
|
|
839
|
-
const profilingEnabled = isTrue(profilingEnabledEnv)
|
|
840
|
-
? 'true'
|
|
841
|
-
: isFalse(profilingEnabledEnv)
|
|
842
|
-
? 'false'
|
|
843
|
-
: profilingEnabledEnv === 'auto' ? 'auto' : undefined
|
|
844
899
|
this._setString(env, 'profiling.enabled', profilingEnabled)
|
|
845
900
|
this._setString(env, 'profiling.exporters', DD_PROFILING_EXPORTERS)
|
|
846
901
|
this._setBoolean(env, 'profiling.sourceMap', DD_PROFILING_SOURCE_MAP && !isFalse(DD_PROFILING_SOURCE_MAP))
|
|
@@ -1347,9 +1402,33 @@ class Config {
|
|
|
1347
1402
|
// eslint-disable-next-line @stylistic/js/max-len
|
|
1348
1403
|
// https://github.com/DataDog/dd-go/blob/prod/trace/apps/tracer-telemetry-intake/telemetry-payload/static/config_norm_rules.json
|
|
1349
1404
|
_merge () {
|
|
1350
|
-
const containers = [
|
|
1351
|
-
|
|
1352
|
-
|
|
1405
|
+
const containers = [
|
|
1406
|
+
this._remote,
|
|
1407
|
+
this._options,
|
|
1408
|
+
this._fleetStableConfig,
|
|
1409
|
+
this._env,
|
|
1410
|
+
this._localStableConfig,
|
|
1411
|
+
this._calculated,
|
|
1412
|
+
this._defaults
|
|
1413
|
+
]
|
|
1414
|
+
const origins = [
|
|
1415
|
+
'remote_config',
|
|
1416
|
+
'code',
|
|
1417
|
+
'fleet_stable_config',
|
|
1418
|
+
'env_var',
|
|
1419
|
+
'local_stable_config',
|
|
1420
|
+
'calculated',
|
|
1421
|
+
'default'
|
|
1422
|
+
]
|
|
1423
|
+
const unprocessedValues = [
|
|
1424
|
+
this._remoteUnprocessed,
|
|
1425
|
+
this._optsUnprocessed,
|
|
1426
|
+
{},
|
|
1427
|
+
this._envUnprocessed,
|
|
1428
|
+
{},
|
|
1429
|
+
{},
|
|
1430
|
+
{}
|
|
1431
|
+
]
|
|
1353
1432
|
const changes = []
|
|
1354
1433
|
|
|
1355
1434
|
for (const name in this._defaults) {
|
|
@@ -1394,6 +1473,21 @@ class Config {
|
|
|
1394
1473
|
}
|
|
1395
1474
|
}
|
|
1396
1475
|
|
|
1476
|
+
function handleOtel (tagString) {
|
|
1477
|
+
return tagString
|
|
1478
|
+
?.replace(/(^|,)deployment\.environment=/, '$1env:')
|
|
1479
|
+
.replace(/(^|,)service\.name=/, '$1service:')
|
|
1480
|
+
.replace(/(^|,)service\.version=/, '$1version:')
|
|
1481
|
+
.replace(/=/g, ':')
|
|
1482
|
+
}
|
|
1483
|
+
|
|
1484
|
+
function parseSpaceSeparatedTags (tagString) {
|
|
1485
|
+
if (tagString && !tagString.includes(',')) {
|
|
1486
|
+
tagString = tagString.replace(/\s+/g, ',')
|
|
1487
|
+
}
|
|
1488
|
+
return tagString
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1397
1491
|
function maybeInt (number) {
|
|
1398
1492
|
const parsed = parseInt(number)
|
|
1399
1493
|
return isNaN(parsed) ? undefined : parsed
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
const os = require('os')
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
|
|
4
|
+
class StableConfig {
|
|
5
|
+
constructor () {
|
|
6
|
+
this.warnings = [] // Logger hasn't been initialized yet, so we can't use log.warn
|
|
7
|
+
this.localEntries = {}
|
|
8
|
+
this.fleetEntries = {}
|
|
9
|
+
this.wasm_loaded = false
|
|
10
|
+
|
|
11
|
+
const { localConfigPath, fleetConfigPath } = this._getStableConfigPaths()
|
|
12
|
+
if (!fs.existsSync(localConfigPath) && !fs.existsSync(fleetConfigPath)) {
|
|
13
|
+
// Bail out early if files don't exist to avoid unnecessary library loading
|
|
14
|
+
return
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const localConfig = this._readConfigFromPath(localConfigPath)
|
|
18
|
+
const fleetConfig = this._readConfigFromPath(fleetConfigPath)
|
|
19
|
+
if (!localConfig && !fleetConfig) {
|
|
20
|
+
// Bail out early if files are empty or we can't read them to avoid unnecessary library loading
|
|
21
|
+
return
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Note: we don't enforce loading because there may be cases where the library is not available and we
|
|
25
|
+
// want to avoid breaking the application. In those cases, we will not have the file-based configuration.
|
|
26
|
+
let libdatadog
|
|
27
|
+
try {
|
|
28
|
+
libdatadog = require('@datadog/libdatadog')
|
|
29
|
+
this.wasm_loaded = true
|
|
30
|
+
} catch (e) {
|
|
31
|
+
this.warnings.push('Can\'t load libdatadog library')
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const libconfig = libdatadog.maybeLoad('library_config')
|
|
36
|
+
if (libconfig === undefined) {
|
|
37
|
+
this.warnings.push('Can\'t load library_config library')
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
try {
|
|
42
|
+
const configurator = new libconfig.JsConfigurator()
|
|
43
|
+
configurator.set_envp(Object.entries(process.env).map(([key, value]) => `${key}=${value}`))
|
|
44
|
+
configurator.set_args(process.argv)
|
|
45
|
+
configurator.get_configuration(localConfig.toString(), fleetConfig.toString()).forEach((entry) => {
|
|
46
|
+
if (entry.source === 'local_stable_config') {
|
|
47
|
+
this.localEntries[entry.name] = entry.value
|
|
48
|
+
} else if (entry.source === 'fleet_stable_config') {
|
|
49
|
+
this.fleetEntries[entry.name] = entry.value
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
} catch (e) {
|
|
53
|
+
this.warnings.push(`Error parsing configuration from file: ${e.message}`)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
_readConfigFromPath (path) {
|
|
58
|
+
try {
|
|
59
|
+
return fs.readFileSync(path, 'utf8')
|
|
60
|
+
} catch (err) {
|
|
61
|
+
if (err.code !== 'ENOENT') {
|
|
62
|
+
this.warnings.push(`Error reading config file at ${path}. ${err.code}: ${err.message}`)
|
|
63
|
+
}
|
|
64
|
+
return '' // Always return a string to avoid undefined.toString() errors
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
_getStableConfigPaths () {
|
|
69
|
+
let localConfigPath = ''
|
|
70
|
+
let fleetConfigPath = ''
|
|
71
|
+
switch (os.type().toLowerCase()) {
|
|
72
|
+
case 'linux':
|
|
73
|
+
localConfigPath = '/etc/datadog-agent/application_monitoring.yaml'
|
|
74
|
+
fleetConfigPath = '/etc/datadog-agent/managed/datadog-agent/stable/application_monitoring.yaml'
|
|
75
|
+
break
|
|
76
|
+
case 'darwin':
|
|
77
|
+
localConfigPath = '/opt/datadog-agent/etc/application_monitoring.yaml'
|
|
78
|
+
fleetConfigPath = '/opt/datadog-agent/etc/managed/datadog-agent/stable/application_monitoring.yaml'
|
|
79
|
+
break
|
|
80
|
+
case 'win32':
|
|
81
|
+
localConfigPath = 'C:\\ProgramData\\Datadog\\application_monitoring.yaml'
|
|
82
|
+
fleetConfigPath = 'C:\\ProgramData\\Datadog\\managed\\datadog-agent\\stable\\application_monitoring.yaml'
|
|
83
|
+
break
|
|
84
|
+
default:
|
|
85
|
+
break
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Allow overriding the paths for testing
|
|
89
|
+
if (process.env.DD_TEST_LOCAL_CONFIG_PATH !== undefined) {
|
|
90
|
+
localConfigPath = process.env.DD_TEST_LOCAL_CONFIG_PATH
|
|
91
|
+
}
|
|
92
|
+
if (process.env.DD_TEST_FLEET_CONFIG_PATH !== undefined) {
|
|
93
|
+
fleetConfigPath = process.env.DD_TEST_FLEET_CONFIG_PATH
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return { localConfigPath, fleetConfigPath }
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
module.exports = StableConfig
|
|
@@ -6,6 +6,7 @@ const dgram = require('dgram')
|
|
|
6
6
|
const isIP = require('net').isIP
|
|
7
7
|
const log = require('./log')
|
|
8
8
|
const { URL, format } = require('url')
|
|
9
|
+
const Histogram = require('./histogram')
|
|
9
10
|
|
|
10
11
|
const MAX_BUFFER_SIZE = 1024 // limit from the agent
|
|
11
12
|
|
|
@@ -193,6 +194,117 @@ class DogStatsDClient {
|
|
|
193
194
|
}
|
|
194
195
|
}
|
|
195
196
|
|
|
197
|
+
// TODO: Handle arrays of tags and tags translation.
|
|
198
|
+
class MetricsAggregationClient {
|
|
199
|
+
constructor (client) {
|
|
200
|
+
this._client = client
|
|
201
|
+
|
|
202
|
+
this.reset()
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
flush () {
|
|
206
|
+
this._captureCounters()
|
|
207
|
+
this._captureGauges()
|
|
208
|
+
this._captureHistograms()
|
|
209
|
+
|
|
210
|
+
this._client.flush()
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
reset () {
|
|
214
|
+
this._counters = {}
|
|
215
|
+
this._gauges = {}
|
|
216
|
+
this._histograms = {}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
distribution (name, value, tag) {
|
|
220
|
+
this._client.distribution(name, value, tag && [tag])
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
boolean (name, value, tag) {
|
|
224
|
+
this.gauge(name, value ? 1 : 0, tag)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
histogram (name, value, tag) {
|
|
228
|
+
this._histograms[name] = this._histograms[name] || new Map()
|
|
229
|
+
|
|
230
|
+
if (!this._histograms[name].has(tag)) {
|
|
231
|
+
this._histograms[name].set(tag, new Histogram())
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
this._histograms[name].get(tag).record(value)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
count (name, count, tag, monotonic = false) {
|
|
238
|
+
if (typeof tag === 'boolean') {
|
|
239
|
+
monotonic = tag
|
|
240
|
+
tag = undefined
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const map = monotonic ? this._counters : this._gauges
|
|
244
|
+
|
|
245
|
+
map[name] = map[name] || new Map()
|
|
246
|
+
|
|
247
|
+
const value = map[name].get(tag) || 0
|
|
248
|
+
|
|
249
|
+
map[name].set(tag, value + count)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
gauge (name, value, tag) {
|
|
253
|
+
this._gauges[name] = this._gauges[name] || new Map()
|
|
254
|
+
this._gauges[name].set(tag, value)
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
increment (name, count = 1, tag, monotonic) {
|
|
258
|
+
this.count(name, count, tag, monotonic)
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
decrement (name, count = 1, tag) {
|
|
262
|
+
this.count(name, -count, tag)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
_captureGauges () {
|
|
266
|
+
Object.keys(this._gauges).forEach(name => {
|
|
267
|
+
this._gauges[name].forEach((value, tag) => {
|
|
268
|
+
this._client.gauge(name, value, tag && [tag])
|
|
269
|
+
})
|
|
270
|
+
})
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
_captureCounters () {
|
|
274
|
+
Object.keys(this._counters).forEach(name => {
|
|
275
|
+
this._counters[name].forEach((value, tag) => {
|
|
276
|
+
this._client.increment(name, value, tag && [tag])
|
|
277
|
+
})
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
this._counters = {}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
_captureHistograms () {
|
|
284
|
+
Object.keys(this._histograms).forEach(name => {
|
|
285
|
+
this._histograms[name].forEach((stats, tag) => {
|
|
286
|
+
const tags = tag && [tag]
|
|
287
|
+
|
|
288
|
+
// Stats can contain garbage data when a value was never recorded.
|
|
289
|
+
if (stats.count === 0) {
|
|
290
|
+
stats = { max: 0, min: 0, sum: 0, avg: 0, median: 0, p95: 0, count: 0, reset: stats.reset }
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
this._client.gauge(`${name}.min`, stats.min, tags)
|
|
294
|
+
this._client.gauge(`${name}.max`, stats.max, tags)
|
|
295
|
+
this._client.increment(`${name}.sum`, stats.sum, tags)
|
|
296
|
+
this._client.increment(`${name}.total`, stats.sum, tags)
|
|
297
|
+
this._client.gauge(`${name}.avg`, stats.avg, tags)
|
|
298
|
+
this._client.increment(`${name}.count`, stats.count, tags)
|
|
299
|
+
this._client.gauge(`${name}.median`, stats.median, tags)
|
|
300
|
+
this._client.gauge(`${name}.95percentile`, stats.p95, tags)
|
|
301
|
+
|
|
302
|
+
stats.reset()
|
|
303
|
+
})
|
|
304
|
+
})
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
196
308
|
/**
|
|
197
309
|
* This is a simplified user-facing proxy to the underlying DogStatsDClient instance
|
|
198
310
|
*
|
|
@@ -201,7 +313,7 @@ class DogStatsDClient {
|
|
|
201
313
|
class CustomMetrics {
|
|
202
314
|
constructor (config) {
|
|
203
315
|
const clientConfig = DogStatsDClient.generateClientConfig(config)
|
|
204
|
-
this.
|
|
316
|
+
this._client = new MetricsAggregationClient(new DogStatsDClient(clientConfig))
|
|
205
317
|
|
|
206
318
|
const flush = this.flush.bind(this)
|
|
207
319
|
|
|
@@ -212,47 +324,43 @@ class CustomMetrics {
|
|
|
212
324
|
}
|
|
213
325
|
|
|
214
326
|
increment (stat, value = 1, tags) {
|
|
215
|
-
|
|
216
|
-
stat,
|
|
217
|
-
|
|
218
|
-
CustomMetrics.tagTranslator(tags)
|
|
219
|
-
)
|
|
327
|
+
for (const tag of this._normalizeTags(tags)) {
|
|
328
|
+
this._client.increment(stat, value, tag)
|
|
329
|
+
}
|
|
220
330
|
}
|
|
221
331
|
|
|
222
332
|
decrement (stat, value = 1, tags) {
|
|
223
|
-
|
|
224
|
-
stat,
|
|
225
|
-
|
|
226
|
-
CustomMetrics.tagTranslator(tags)
|
|
227
|
-
)
|
|
333
|
+
for (const tag of this._normalizeTags(tags)) {
|
|
334
|
+
this._client.decrement(stat, value, tag)
|
|
335
|
+
}
|
|
228
336
|
}
|
|
229
337
|
|
|
230
338
|
gauge (stat, value, tags) {
|
|
231
|
-
|
|
232
|
-
stat,
|
|
233
|
-
|
|
234
|
-
CustomMetrics.tagTranslator(tags)
|
|
235
|
-
)
|
|
339
|
+
for (const tag of this._normalizeTags(tags)) {
|
|
340
|
+
this._client.gauge(stat, value, tag)
|
|
341
|
+
}
|
|
236
342
|
}
|
|
237
343
|
|
|
238
344
|
distribution (stat, value, tags) {
|
|
239
|
-
|
|
240
|
-
stat,
|
|
241
|
-
|
|
242
|
-
CustomMetrics.tagTranslator(tags)
|
|
243
|
-
)
|
|
345
|
+
for (const tag of this._normalizeTags(tags)) {
|
|
346
|
+
this._client.distribution(stat, value, tag)
|
|
347
|
+
}
|
|
244
348
|
}
|
|
245
349
|
|
|
246
350
|
histogram (stat, value, tags) {
|
|
247
|
-
|
|
248
|
-
stat,
|
|
249
|
-
|
|
250
|
-
CustomMetrics.tagTranslator(tags)
|
|
251
|
-
)
|
|
351
|
+
for (const tag of this._normalizeTags(tags)) {
|
|
352
|
+
this._client.histogram(stat, value, tag)
|
|
353
|
+
}
|
|
252
354
|
}
|
|
253
355
|
|
|
254
356
|
flush () {
|
|
255
|
-
return this.
|
|
357
|
+
return this._client.flush()
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
_normalizeTags (tags) {
|
|
361
|
+
tags = CustomMetrics.tagTranslator(tags)
|
|
362
|
+
|
|
363
|
+
return tags.length === 0 ? [undefined] : tags
|
|
256
364
|
}
|
|
257
365
|
|
|
258
366
|
/**
|
|
@@ -274,5 +382,6 @@ class CustomMetrics {
|
|
|
274
382
|
|
|
275
383
|
module.exports = {
|
|
276
384
|
DogStatsDClient,
|
|
277
|
-
CustomMetrics
|
|
385
|
+
CustomMetrics,
|
|
386
|
+
MetricsAggregationClient
|
|
278
387
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const log = require('../../log')
|
|
4
4
|
const { storage: llmobsStorage } = require('../storage')
|
|
5
|
+
const telemetry = require('../telemetry')
|
|
5
6
|
|
|
6
7
|
const TracingPlugin = require('../../plugins/tracing')
|
|
7
8
|
const LLMObsTagger = require('../tagger')
|
|
@@ -36,6 +37,8 @@ class LLMObsPlugin extends TracingPlugin {
|
|
|
36
37
|
// register options may not be set for operations we do not trace with llmobs
|
|
37
38
|
// ie OpenAI fine tuning jobs, file jobs, etc.
|
|
38
39
|
if (registerOptions) {
|
|
40
|
+
telemetry.incrementLLMObsSpanStartCount({ autoinstrumented: true, integration: this.constructor.id })
|
|
41
|
+
|
|
39
42
|
ctx.llmobs = {} // initialize context-based namespace
|
|
40
43
|
llmobsStorage.enterWith({ span })
|
|
41
44
|
ctx.llmobs.parent = parent
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const BaseLLMObsPlugin = require('./base')
|
|
2
2
|
const { storage } = require('../../../../datadog-core')
|
|
3
3
|
const llmobsStore = storage('llmobs')
|
|
4
|
+
const telemetry = require('../telemetry')
|
|
4
5
|
|
|
5
6
|
const {
|
|
6
7
|
extractRequestParams,
|
|
@@ -46,6 +47,8 @@ class BedrockRuntimeLLMObsPlugin extends BaseLLMObsPlugin {
|
|
|
46
47
|
}
|
|
47
48
|
|
|
48
49
|
setLLMObsTags ({ request, span, response, modelProvider, modelName }) {
|
|
50
|
+
telemetry.incrementLLMObsSpanStartCount({ autoinstrumented: true, integration: 'bedrock' })
|
|
51
|
+
|
|
49
52
|
const parent = llmobsStore.getStore()?.span
|
|
50
53
|
this._tagger.registerLLMObsSpan(span, {
|
|
51
54
|
parent,
|
|
@@ -21,6 +21,7 @@ const LlmHandler = require('./handlers/llm')
|
|
|
21
21
|
const EmbeddingHandler = require('./handlers/embedding')
|
|
22
22
|
|
|
23
23
|
class LangChainLLMObsPlugin extends LLMObsPlugin {
|
|
24
|
+
static get id () { return 'langchain' }
|
|
24
25
|
static get prefix () {
|
|
25
26
|
return 'tracing:apm:langchain:invoke'
|
|
26
27
|
}
|
|
@@ -14,6 +14,7 @@ const Span = require('../opentracing/span')
|
|
|
14
14
|
|
|
15
15
|
const tracerVersion = require('../../../../package.json').version
|
|
16
16
|
const logger = require('../log')
|
|
17
|
+
const telemetry = require('./telemetry')
|
|
17
18
|
|
|
18
19
|
const LLMObsTagger = require('./tagger')
|
|
19
20
|
|
|
@@ -88,6 +89,8 @@ class LLMObs extends NoopLLMObs {
|
|
|
88
89
|
|
|
89
90
|
const kind = validateKind(options.kind) // will throw if kind is undefined or not an expected kind
|
|
90
91
|
|
|
92
|
+
telemetry.incrementLLMObsSpanStartCount({ autoinstrumented: false, kind })
|
|
93
|
+
|
|
91
94
|
// name is required for spans generated with `trace`
|
|
92
95
|
// while `kind` is required, this should never throw (as otherwise it would have thrown above)
|
|
93
96
|
const name = options.name || kind
|
|
@@ -133,6 +136,8 @@ class LLMObs extends NoopLLMObs {
|
|
|
133
136
|
const llmobs = this
|
|
134
137
|
|
|
135
138
|
function wrapped () {
|
|
139
|
+
telemetry.incrementLLMObsSpanStartCount({ autoinstrumented: false, kind })
|
|
140
|
+
|
|
136
141
|
const span = llmobs._tracer.scope().active()
|
|
137
142
|
const fnArgs = arguments
|
|
138
143
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const telemetryMetrics = require('../telemetry/metrics')
|
|
4
|
+
const llmobsMetrics = telemetryMetrics.manager.namespace('mlobs')
|
|
5
|
+
|
|
6
|
+
function incrementLLMObsSpanStartCount (tags, value = 1) {
|
|
7
|
+
llmobsMetrics.count('span.start', tags).inc(value)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
module.exports = {
|
|
11
|
+
incrementLLMObsSpanStartCount
|
|
12
|
+
}
|
|
@@ -105,23 +105,36 @@ const log = {
|
|
|
105
105
|
|
|
106
106
|
deprecate (code, message) {
|
|
107
107
|
return this._deprecate(code, message)
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
isEnabled (fleetStableConfigValue = undefined, localStableConfigValue = undefined) {
|
|
111
|
+
return isTrue(coalesce(
|
|
112
|
+
fleetStableConfigValue,
|
|
113
|
+
process.env?.DD_TRACE_DEBUG,
|
|
114
|
+
process.env?.OTEL_LOG_LEVEL === 'debug' || undefined,
|
|
115
|
+
localStableConfigValue,
|
|
116
|
+
config.enabled
|
|
117
|
+
))
|
|
118
|
+
},
|
|
119
|
+
|
|
120
|
+
getLogLevel (
|
|
121
|
+
optionsValue = undefined,
|
|
122
|
+
fleetStableConfigValue = undefined,
|
|
123
|
+
localStableConfigValue = undefined
|
|
124
|
+
) {
|
|
125
|
+
return coalesce(
|
|
126
|
+
optionsValue,
|
|
127
|
+
fleetStableConfigValue,
|
|
128
|
+
process.env?.DD_TRACE_LOG_LEVEL,
|
|
129
|
+
process.env?.OTEL_LOG_LEVEL,
|
|
130
|
+
localStableConfigValue,
|
|
131
|
+
config.logLevel
|
|
132
|
+
)
|
|
108
133
|
}
|
|
109
134
|
}
|
|
110
135
|
|
|
111
136
|
log.reset()
|
|
112
137
|
|
|
113
|
-
|
|
114
|
-
process.env.DD_TRACE_DEBUG,
|
|
115
|
-
process.env.OTEL_LOG_LEVEL === 'debug',
|
|
116
|
-
config.enabled
|
|
117
|
-
))
|
|
118
|
-
|
|
119
|
-
const logLevel = coalesce(
|
|
120
|
-
process.env.DD_TRACE_LOG_LEVEL,
|
|
121
|
-
process.env.OTEL_LOG_LEVEL,
|
|
122
|
-
config.logLevel
|
|
123
|
-
)
|
|
124
|
-
|
|
125
|
-
log.toggle(enabled, logLevel)
|
|
138
|
+
log.toggle(log.isEnabled(), log.getLogLevel())
|
|
126
139
|
|
|
127
140
|
module.exports = log
|
|
@@ -103,10 +103,6 @@ module.exports = class PluginManager {
|
|
|
103
103
|
this._tracerConfig = config
|
|
104
104
|
this._tracer._nomenclature.configure(config)
|
|
105
105
|
|
|
106
|
-
if (!config._isInServerlessEnvironment?.()) {
|
|
107
|
-
maybeEnable(require('../../datadog-plugin-fetch/src'))
|
|
108
|
-
}
|
|
109
|
-
|
|
110
106
|
for (const name in pluginClasses) {
|
|
111
107
|
this.loadPlugin(name)
|
|
112
108
|
}
|
|
@@ -39,6 +39,7 @@ module.exports = {
|
|
|
39
39
|
get express () { return require('../../../datadog-plugin-express/src') },
|
|
40
40
|
get fastify () { return require('../../../datadog-plugin-fastify/src') },
|
|
41
41
|
get 'find-my-way' () { return require('../../../datadog-plugin-find-my-way/src') },
|
|
42
|
+
get 'global:fetch' () { return require('../../../datadog-plugin-fetch/src') },
|
|
42
43
|
get graphql () { return require('../../../datadog-plugin-graphql/src') },
|
|
43
44
|
get grpc () { return require('../../../datadog-plugin-grpc/src') },
|
|
44
45
|
get hapi () { return require('../../../datadog-plugin-hapi/src') },
|
|
@@ -328,22 +328,34 @@ function getGitMetadata (ciMetadata) {
|
|
|
328
328
|
committerDate
|
|
329
329
|
] = sanitizedExec('git', ['show', '-s', '--format=%an,%ae,%aI,%cn,%ce,%cI']).split(',')
|
|
330
330
|
|
|
331
|
-
|
|
332
|
-
[GIT_REPOSITORY_URL]:
|
|
333
|
-
filterSensitiveInfoFromRepository(repositoryUrl || sanitizedExec('git', ['ls-remote', '--get-url'])),
|
|
331
|
+
const tags = {
|
|
334
332
|
[GIT_COMMIT_MESSAGE]:
|
|
335
333
|
commitMessage || sanitizedExec('git', ['show', '-s', '--format=%s']),
|
|
336
|
-
[GIT_COMMIT_AUTHOR_DATE]: authorDate,
|
|
337
|
-
[GIT_COMMIT_AUTHOR_NAME]: ciAuthorName || authorName,
|
|
338
|
-
[GIT_COMMIT_AUTHOR_EMAIL]: ciAuthorEmail || authorEmail,
|
|
339
|
-
[GIT_COMMIT_COMMITTER_DATE]: committerDate,
|
|
340
|
-
[GIT_COMMIT_COMMITTER_NAME]: committerName,
|
|
341
|
-
[GIT_COMMIT_COMMITTER_EMAIL]: committerEmail,
|
|
342
334
|
[GIT_BRANCH]: branch || sanitizedExec('git', ['rev-parse', '--abbrev-ref', 'HEAD']),
|
|
343
335
|
[GIT_COMMIT_SHA]: commitSHA || sanitizedExec('git', ['rev-parse', 'HEAD']),
|
|
344
|
-
[GIT_TAG]: tag,
|
|
345
336
|
[CI_WORKSPACE_PATH]: ciWorkspacePath || sanitizedExec('git', ['rev-parse', '--show-toplevel'])
|
|
346
337
|
}
|
|
338
|
+
|
|
339
|
+
const entries = [
|
|
340
|
+
GIT_REPOSITORY_URL,
|
|
341
|
+
filterSensitiveInfoFromRepository(repositoryUrl || sanitizedExec('git', ['ls-remote', '--get-url'])),
|
|
342
|
+
GIT_COMMIT_AUTHOR_DATE, authorDate,
|
|
343
|
+
GIT_COMMIT_AUTHOR_NAME, ciAuthorName || authorName,
|
|
344
|
+
GIT_COMMIT_AUTHOR_EMAIL, ciAuthorEmail || authorEmail,
|
|
345
|
+
GIT_COMMIT_COMMITTER_DATE, committerDate,
|
|
346
|
+
GIT_COMMIT_COMMITTER_NAME, committerName,
|
|
347
|
+
GIT_COMMIT_COMMITTER_EMAIL, committerEmail,
|
|
348
|
+
GIT_TAG, tag
|
|
349
|
+
]
|
|
350
|
+
|
|
351
|
+
for (let i = 0; i < entries.length; i += 2) {
|
|
352
|
+
const value = entries[i + 1]
|
|
353
|
+
if (value) {
|
|
354
|
+
tags[entries[i]] = value
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
return tags
|
|
347
359
|
}
|
|
348
360
|
|
|
349
361
|
module.exports = {
|
|
@@ -475,8 +475,9 @@ function addRequestTags (context, spanType) {
|
|
|
475
475
|
function addResponseTags (context) {
|
|
476
476
|
const { req, res, paths, span, inferredProxySpan } = context
|
|
477
477
|
|
|
478
|
-
|
|
479
|
-
|
|
478
|
+
const route = paths.join('')
|
|
479
|
+
if (route) {
|
|
480
|
+
span.setTag(HTTP_ROUTE, route)
|
|
480
481
|
}
|
|
481
482
|
|
|
482
483
|
span.addTags({
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
const v8 = require('v8')
|
|
6
6
|
const os = require('os')
|
|
7
|
-
const { DogStatsDClient } = require('../dogstatsd')
|
|
7
|
+
const { DogStatsDClient, MetricsAggregationClient } = require('../dogstatsd')
|
|
8
8
|
const log = require('../log')
|
|
9
9
|
const Histogram = require('../histogram')
|
|
10
10
|
const { performance, PerformanceObserver } = require('perf_hooks')
|
|
@@ -25,9 +25,6 @@ let interval
|
|
|
25
25
|
let client
|
|
26
26
|
let time
|
|
27
27
|
let cpuUsage
|
|
28
|
-
let gauges
|
|
29
|
-
let counters
|
|
30
|
-
let histograms
|
|
31
28
|
let elu
|
|
32
29
|
|
|
33
30
|
reset()
|
|
@@ -49,7 +46,7 @@ const runtimeMetrics = module.exports = {
|
|
|
49
46
|
nativeMetrics = null
|
|
50
47
|
}
|
|
51
48
|
|
|
52
|
-
client = new DogStatsDClient(clientConfig)
|
|
49
|
+
client = new MetricsAggregationClient(new DogStatsDClient(clientConfig))
|
|
53
50
|
|
|
54
51
|
time = process.hrtime()
|
|
55
52
|
|
|
@@ -98,50 +95,27 @@ const runtimeMetrics = module.exports = {
|
|
|
98
95
|
},
|
|
99
96
|
|
|
100
97
|
boolean (name, value, tag) {
|
|
101
|
-
|
|
98
|
+
client && client.boolean(name, value, tag)
|
|
102
99
|
},
|
|
103
100
|
|
|
104
101
|
histogram (name, value, tag) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
histograms[name] = histograms[name] || new Map()
|
|
108
|
-
|
|
109
|
-
if (!histograms[name].has(tag)) {
|
|
110
|
-
histograms[name].set(tag, new Histogram())
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
histograms[name].get(tag).record(value)
|
|
102
|
+
client && client.histogram(name, value, tag)
|
|
114
103
|
},
|
|
115
104
|
|
|
116
105
|
count (name, count, tag, monotonic = false) {
|
|
117
|
-
|
|
118
|
-
if (typeof tag === 'boolean') {
|
|
119
|
-
monotonic = tag
|
|
120
|
-
tag = undefined
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const map = monotonic ? counters : gauges
|
|
124
|
-
|
|
125
|
-
map[name] = map[name] || new Map()
|
|
126
|
-
|
|
127
|
-
const value = map[name].get(tag) || 0
|
|
128
|
-
|
|
129
|
-
map[name].set(tag, value + count)
|
|
106
|
+
client && client.count(name, count, tag, monotonic)
|
|
130
107
|
},
|
|
131
108
|
|
|
132
109
|
gauge (name, value, tag) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
gauges[name] = gauges[name] || new Map()
|
|
136
|
-
gauges[name].set(tag, value)
|
|
110
|
+
client && client.gauge(name, value, tag)
|
|
137
111
|
},
|
|
138
112
|
|
|
139
113
|
increment (name, tag, monotonic) {
|
|
140
|
-
|
|
114
|
+
client && client.increment(name, 1, tag, monotonic)
|
|
141
115
|
},
|
|
142
116
|
|
|
143
117
|
decrement (name, tag) {
|
|
144
|
-
|
|
118
|
+
client && client.decrement(name, 1, tag)
|
|
145
119
|
}
|
|
146
120
|
}
|
|
147
121
|
|
|
@@ -150,9 +124,6 @@ function reset () {
|
|
|
150
124
|
client = null
|
|
151
125
|
time = null
|
|
152
126
|
cpuUsage = null
|
|
153
|
-
gauges = {}
|
|
154
|
-
counters = {}
|
|
155
|
-
histograms = {}
|
|
156
127
|
nativeMetrics = null
|
|
157
128
|
gcObserver && gcObserver.disconnect()
|
|
158
129
|
gcObserver = null
|
|
@@ -246,33 +217,6 @@ function captureGCMetrics () {
|
|
|
246
217
|
gcProfiler.start()
|
|
247
218
|
}
|
|
248
219
|
|
|
249
|
-
function captureGauges () {
|
|
250
|
-
Object.keys(gauges).forEach(name => {
|
|
251
|
-
gauges[name].forEach((value, tag) => {
|
|
252
|
-
client.gauge(name, value, tag && [tag])
|
|
253
|
-
})
|
|
254
|
-
})
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
function captureCounters () {
|
|
258
|
-
Object.keys(counters).forEach(name => {
|
|
259
|
-
counters[name].forEach((value, tag) => {
|
|
260
|
-
client.increment(name, value, tag && [tag])
|
|
261
|
-
})
|
|
262
|
-
})
|
|
263
|
-
|
|
264
|
-
counters = {}
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
function captureHistograms () {
|
|
268
|
-
Object.keys(histograms).forEach(name => {
|
|
269
|
-
histograms[name].forEach((stats, tag) => {
|
|
270
|
-
histogram(name, stats, tag && [tag])
|
|
271
|
-
stats.reset()
|
|
272
|
-
})
|
|
273
|
-
})
|
|
274
|
-
}
|
|
275
|
-
|
|
276
220
|
/**
|
|
277
221
|
* Gathers and reports Event Loop Utilization (ELU) since last run
|
|
278
222
|
*
|
|
@@ -295,9 +239,6 @@ function captureCommonMetrics () {
|
|
|
295
239
|
captureMemoryUsage()
|
|
296
240
|
captureProcess()
|
|
297
241
|
captureHeapStats()
|
|
298
|
-
captureGauges()
|
|
299
|
-
captureCounters()
|
|
300
|
-
captureHistograms()
|
|
301
242
|
captureELU()
|
|
302
243
|
captureGCMetrics()
|
|
303
244
|
}
|
|
@@ -339,21 +280,15 @@ function captureNativeMetrics () {
|
|
|
339
280
|
}
|
|
340
281
|
|
|
341
282
|
function histogram (name, stats, tags) {
|
|
342
|
-
tags = [].concat(tags)
|
|
283
|
+
tags = tags ? [].concat(tags) : []
|
|
343
284
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
285
|
+
if (tags.length > 0) {
|
|
286
|
+
for (const tag of tags) {
|
|
287
|
+
client.histogram(name, stats, tag)
|
|
288
|
+
}
|
|
289
|
+
} else {
|
|
290
|
+
client.histogram(name, stats)
|
|
347
291
|
}
|
|
348
|
-
|
|
349
|
-
client.gauge(`${name}.min`, stats.min, tags)
|
|
350
|
-
client.gauge(`${name}.max`, stats.max, tags)
|
|
351
|
-
client.increment(`${name}.sum`, stats.sum, tags)
|
|
352
|
-
client.increment(`${name}.total`, stats.sum, tags)
|
|
353
|
-
client.gauge(`${name}.avg`, stats.avg, tags)
|
|
354
|
-
client.increment(`${name}.count`, stats.count, tags)
|
|
355
|
-
client.gauge(`${name}.median`, stats.median, tags)
|
|
356
|
-
client.gauge(`${name}.95percentile`, stats.p95, tags)
|
|
357
292
|
}
|
|
358
293
|
|
|
359
294
|
function startGCObserver () {
|
|
@@ -6,13 +6,7 @@ const ERROR_MESSAGE = constants.ERROR_MESSAGE
|
|
|
6
6
|
const ERROR_STACK = constants.ERROR_STACK
|
|
7
7
|
const ERROR_TYPE = constants.ERROR_TYPE
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
'deployment.environment': 'env',
|
|
11
|
-
'service.name': 'service',
|
|
12
|
-
'service.version': 'version'
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function add (carrier, keyValuePairs, parseOtelTags = false) {
|
|
9
|
+
function add (carrier, keyValuePairs) {
|
|
16
10
|
if (!carrier || !keyValuePairs) return
|
|
17
11
|
|
|
18
12
|
if (Array.isArray(keyValuePairs)) {
|
|
@@ -22,14 +16,13 @@ function add (carrier, keyValuePairs, parseOtelTags = false) {
|
|
|
22
16
|
if (typeof keyValuePairs === 'string') {
|
|
23
17
|
const segments = keyValuePairs.split(',')
|
|
24
18
|
for (const segment of segments) {
|
|
25
|
-
const separatorIndex =
|
|
26
|
-
if (separatorIndex === -1) continue
|
|
27
|
-
|
|
28
|
-
let key = segment.slice(0, separatorIndex)
|
|
29
|
-
const value = segment.slice(separatorIndex + 1)
|
|
19
|
+
const separatorIndex = segment.indexOf(':')
|
|
30
20
|
|
|
31
|
-
|
|
32
|
-
|
|
21
|
+
let value = ''
|
|
22
|
+
let key = segment
|
|
23
|
+
if (separatorIndex !== -1) {
|
|
24
|
+
key = segment.slice(0, separatorIndex)
|
|
25
|
+
value = segment.slice(separatorIndex + 1)
|
|
33
26
|
}
|
|
34
27
|
|
|
35
28
|
carrier[key.trim()] = value.trim()
|
|
@@ -79,11 +79,20 @@ function hasOwn (object, prop) {
|
|
|
79
79
|
return Object.prototype.hasOwnProperty.call(object, prop)
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
function normalizeProfilingEnabledValue (configValue) {
|
|
83
|
+
return isTrue(configValue)
|
|
84
|
+
? 'true'
|
|
85
|
+
: isFalse(configValue)
|
|
86
|
+
? 'false'
|
|
87
|
+
: configValue === 'auto' ? 'auto' : undefined
|
|
88
|
+
}
|
|
89
|
+
|
|
82
90
|
module.exports = {
|
|
83
91
|
isTrue,
|
|
84
92
|
isFalse,
|
|
85
93
|
isError,
|
|
86
94
|
globMatch,
|
|
87
95
|
calculateDDBasePath,
|
|
88
|
-
hasOwn
|
|
96
|
+
hasOwn,
|
|
97
|
+
normalizeProfilingEnabledValue
|
|
89
98
|
}
|