dd-trace 5.25.0 → 5.27.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-3rdparty.csv +2 -0
- package/index.d.ts +17 -8
- package/init.js +60 -47
- package/package.json +5 -2
- package/packages/datadog-core/index.js +1 -3
- package/packages/datadog-core/src/storage.js +21 -0
- package/packages/datadog-instrumentations/src/express.js +1 -1
- package/packages/datadog-instrumentations/src/handlebars.js +40 -0
- package/packages/datadog-instrumentations/src/helpers/hooks.js +5 -0
- package/packages/datadog-instrumentations/src/jest.js +6 -2
- package/packages/datadog-instrumentations/src/langchain.js +77 -0
- package/packages/datadog-instrumentations/src/next.js +19 -7
- package/packages/datadog-instrumentations/src/pug.js +23 -0
- package/packages/datadog-instrumentations/src/router.js +2 -3
- package/packages/datadog-plugin-aws-sdk/src/base.js +5 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +7 -6
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +34 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +8 -8
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +59 -45
- package/packages/datadog-plugin-cypress/src/support.js +1 -0
- package/packages/datadog-plugin-http/src/client.js +42 -1
- package/packages/datadog-plugin-http2/src/client.js +26 -1
- package/packages/datadog-plugin-langchain/src/handlers/chain.js +50 -0
- package/packages/datadog-plugin-langchain/src/handlers/default.js +53 -0
- package/packages/datadog-plugin-langchain/src/handlers/embedding.js +63 -0
- package/packages/datadog-plugin-langchain/src/handlers/language_models/chat_model.js +99 -0
- package/packages/datadog-plugin-langchain/src/handlers/language_models/index.js +48 -0
- package/packages/datadog-plugin-langchain/src/handlers/language_models/llm.js +57 -0
- package/packages/datadog-plugin-langchain/src/index.js +89 -0
- package/packages/datadog-plugin-langchain/src/tokens.js +35 -0
- package/packages/datadog-plugin-mocha/src/index.js +1 -1
- package/packages/datadog-plugin-moleculer/src/server.js +0 -1
- package/packages/dd-trace/src/appsec/api_security_sampler.js +50 -27
- package/packages/dd-trace/src/appsec/iast/analyzers/analyzers.js +1 -0
- package/packages/dd-trace/src/appsec/iast/analyzers/header-injection-analyzer.js +33 -16
- package/packages/dd-trace/src/appsec/iast/analyzers/template-injection-analyzer.js +18 -0
- package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-handler.js +3 -2
- package/packages/dd-trace/src/appsec/iast/vulnerabilities.js +1 -0
- package/packages/dd-trace/src/appsec/index.js +6 -6
- package/packages/dd-trace/src/appsec/recommended.json +353 -155
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +1 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +0 -7
- package/packages/dd-trace/src/appsec/reporter.js +1 -0
- package/packages/dd-trace/src/appsec/sdk/utils.js +21 -2
- package/packages/dd-trace/src/config.js +21 -4
- package/packages/dd-trace/src/constants.js +6 -1
- package/packages/dd-trace/src/crashtracking/crashtracker.js +98 -0
- package/packages/dd-trace/src/crashtracking/index.js +15 -0
- package/packages/dd-trace/src/crashtracking/noop.js +8 -0
- package/packages/dd-trace/src/llmobs/sdk.js +1 -1
- package/packages/dd-trace/src/llmobs/span_processor.js +1 -1
- package/packages/dd-trace/src/llmobs/writers/spans/base.js +3 -0
- package/packages/dd-trace/src/log/index.js +10 -13
- package/packages/dd-trace/src/log/log.js +52 -0
- package/packages/dd-trace/src/log/writer.js +50 -19
- package/packages/dd-trace/src/noop/span.js +1 -0
- package/packages/dd-trace/src/opentelemetry/span.js +15 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +35 -22
- package/packages/dd-trace/src/opentracing/span.js +14 -0
- package/packages/dd-trace/src/opentracing/span_context.js +1 -0
- package/packages/dd-trace/src/plugins/index.js +3 -0
- package/packages/dd-trace/src/plugins/tracing.js +2 -2
- package/packages/dd-trace/src/plugins/util/inferred_proxy.js +121 -0
- package/packages/dd-trace/src/plugins/util/ip_extractor.js +0 -1
- package/packages/dd-trace/src/plugins/util/web.js +39 -11
- package/packages/dd-trace/src/profiling/exporters/agent.js +42 -5
- package/packages/dd-trace/src/profiling/profiler.js +5 -2
- package/packages/dd-trace/src/proxy.js +5 -0
- package/packages/dd-trace/src/telemetry/logs/index.js +16 -11
- package/packages/dd-trace/src/telemetry/logs/log-collector.js +3 -8
- package/packages/dd-trace/src/telemetry/metrics.js +6 -1
- package/packages/dd-trace/src/util.js +16 -1
- package/version.js +4 -2
- /package/packages/dd-trace/src/appsec/iast/vulnerabilities-formatter/evidence-redaction/sensitive-analyzers/{code-injection-sensitive-analyzer.js → tainted-range-based-sensitive-analyzer.js} +0 -0
|
@@ -11,7 +11,7 @@ module.exports = {
|
|
|
11
11
|
ASM_CUSTOM_RULES: 1n << 8n,
|
|
12
12
|
ASM_CUSTOM_BLOCKING_RESPONSE: 1n << 9n,
|
|
13
13
|
ASM_TRUSTED_IPS: 1n << 10n,
|
|
14
|
-
ASM_API_SECURITY_SAMPLE_RATE: 1n << 11n,
|
|
14
|
+
ASM_API_SECURITY_SAMPLE_RATE: 1n << 11n, // deprecated
|
|
15
15
|
APM_TRACING_SAMPLE_RATE: 1n << 12n,
|
|
16
16
|
APM_TRACING_LOGS_INJECTION: 1n << 13n,
|
|
17
17
|
APM_TRACING_HTTP_HEADER_TAGS: 1n << 14n,
|
|
@@ -4,7 +4,6 @@ const Activation = require('../activation')
|
|
|
4
4
|
|
|
5
5
|
const RemoteConfigManager = require('./manager')
|
|
6
6
|
const RemoteConfigCapabilities = require('./capabilities')
|
|
7
|
-
const apiSecuritySampler = require('../api_security_sampler')
|
|
8
7
|
|
|
9
8
|
let rc
|
|
10
9
|
|
|
@@ -24,18 +23,12 @@ function enable (config, appsec) {
|
|
|
24
23
|
rc.updateCapabilities(RemoteConfigCapabilities.ASM_ACTIVATION, true)
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
if (config.appsec.apiSecurity?.enabled) {
|
|
28
|
-
rc.updateCapabilities(RemoteConfigCapabilities.ASM_API_SECURITY_SAMPLE_RATE, true)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
26
|
rc.setProductHandler('ASM_FEATURES', (action, rcConfig) => {
|
|
32
27
|
if (!rcConfig) return
|
|
33
28
|
|
|
34
29
|
if (activation === Activation.ONECLICK) {
|
|
35
30
|
enableOrDisableAppsec(action, rcConfig, config, appsec)
|
|
36
31
|
}
|
|
37
|
-
|
|
38
|
-
apiSecuritySampler.setRequestSampling(rcConfig.api_security?.request_sample_rate)
|
|
39
32
|
})
|
|
40
33
|
}
|
|
41
34
|
|
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
function getRootSpan (tracer) {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
let span = tracer.scope().active()
|
|
5
|
+
if (!span) return
|
|
6
|
+
|
|
7
|
+
const context = span.context()
|
|
8
|
+
const started = context._trace.started
|
|
9
|
+
|
|
10
|
+
let parentId = context._parentId
|
|
11
|
+
while (parentId) {
|
|
12
|
+
const parent = started.find(s => s.context()._spanId === parentId)
|
|
13
|
+
const pContext = parent?.context()
|
|
14
|
+
|
|
15
|
+
if (!pContext) break
|
|
16
|
+
|
|
17
|
+
parentId = pContext._parentId
|
|
18
|
+
|
|
19
|
+
if (!pContext._tags?._inferred_span) {
|
|
20
|
+
span = parent
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return span
|
|
6
25
|
}
|
|
7
26
|
|
|
8
27
|
module.exports = {
|
|
@@ -444,7 +444,7 @@ class Config {
|
|
|
444
444
|
const defaults = setHiddenProperty(this, '_defaults', {})
|
|
445
445
|
|
|
446
446
|
this._setValue(defaults, 'appsec.apiSecurity.enabled', true)
|
|
447
|
-
this._setValue(defaults, 'appsec.apiSecurity.
|
|
447
|
+
this._setValue(defaults, 'appsec.apiSecurity.sampleDelay', 30)
|
|
448
448
|
this._setValue(defaults, 'appsec.blockedTemplateGraphql', undefined)
|
|
449
449
|
this._setValue(defaults, 'appsec.blockedTemplateHtml', undefined)
|
|
450
450
|
this._setValue(defaults, 'appsec.blockedTemplateJson', undefined)
|
|
@@ -467,6 +467,7 @@ class Config {
|
|
|
467
467
|
this._setValue(defaults, 'ciVisibilityTestSessionName', '')
|
|
468
468
|
this._setValue(defaults, 'clientIpEnabled', false)
|
|
469
469
|
this._setValue(defaults, 'clientIpHeader', null)
|
|
470
|
+
this._setValue(defaults, 'crashtracking.enabled', false)
|
|
470
471
|
this._setValue(defaults, 'codeOriginForSpans.enabled', false)
|
|
471
472
|
this._setValue(defaults, 'dbmPropagationMode', 'disabled')
|
|
472
473
|
this._setValue(defaults, 'dogstatsd.hostname', '127.0.0.1')
|
|
@@ -504,6 +505,8 @@ class Config {
|
|
|
504
505
|
this._setValue(defaults, 'isGitUploadEnabled', false)
|
|
505
506
|
this._setValue(defaults, 'isIntelligentTestRunnerEnabled', false)
|
|
506
507
|
this._setValue(defaults, 'isManualApiEnabled', false)
|
|
508
|
+
this._setValue(defaults, 'langchain.spanCharLimit', 128)
|
|
509
|
+
this._setValue(defaults, 'langchain.spanPromptCompletionSampleRate', 1.0)
|
|
507
510
|
this._setValue(defaults, 'llmobs.agentlessEnabled', false)
|
|
508
511
|
this._setValue(defaults, 'llmobs.enabled', false)
|
|
509
512
|
this._setValue(defaults, 'llmobs.mlApp', undefined)
|
|
@@ -513,6 +516,7 @@ class Config {
|
|
|
513
516
|
this._setValue(defaults, 'isTestDynamicInstrumentationEnabled', false)
|
|
514
517
|
this._setValue(defaults, 'logInjection', false)
|
|
515
518
|
this._setValue(defaults, 'lookup', undefined)
|
|
519
|
+
this._setValue(defaults, 'inferredProxyServicesEnabled', false)
|
|
516
520
|
this._setValue(defaults, 'memcachedCommandEnabled', false)
|
|
517
521
|
this._setValue(defaults, 'openAiLogsEnabled', false)
|
|
518
522
|
this._setValue(defaults, 'openaiSpanCharLimit', 128)
|
|
@@ -569,7 +573,7 @@ class Config {
|
|
|
569
573
|
AWS_LAMBDA_FUNCTION_NAME,
|
|
570
574
|
DD_AGENT_HOST,
|
|
571
575
|
DD_API_SECURITY_ENABLED,
|
|
572
|
-
|
|
576
|
+
DD_API_SECURITY_SAMPLE_DELAY,
|
|
573
577
|
DD_APPSEC_AUTOMATED_USER_EVENTS_TRACKING,
|
|
574
578
|
DD_APPSEC_ENABLED,
|
|
575
579
|
DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON,
|
|
@@ -585,6 +589,7 @@ class Config {
|
|
|
585
589
|
DD_APPSEC_RASP_ENABLED,
|
|
586
590
|
DD_APPSEC_TRACE_RATE_LIMIT,
|
|
587
591
|
DD_APPSEC_WAF_TIMEOUT,
|
|
592
|
+
DD_CRASHTRACKING_ENABLED,
|
|
588
593
|
DD_CODE_ORIGIN_FOR_SPANS_ENABLED,
|
|
589
594
|
DD_DATA_STREAMS_ENABLED,
|
|
590
595
|
DD_DBM_PROPAGATION_MODE,
|
|
@@ -612,6 +617,8 @@ class Config {
|
|
|
612
617
|
DD_INSTRUMENTATION_TELEMETRY_ENABLED,
|
|
613
618
|
DD_INSTRUMENTATION_CONFIG_ID,
|
|
614
619
|
DD_LOGS_INJECTION,
|
|
620
|
+
DD_LANGCHAIN_SPAN_CHAR_LIMIT,
|
|
621
|
+
DD_LANGCHAIN_SPAN_PROMPT_COMPLETION_SAMPLE_RATE,
|
|
615
622
|
DD_LLMOBS_AGENTLESS_ENABLED,
|
|
616
623
|
DD_LLMOBS_ENABLED,
|
|
617
624
|
DD_LLMOBS_ML_APP,
|
|
@@ -675,6 +682,7 @@ class Config {
|
|
|
675
682
|
DD_TRACE_X_DATADOG_TAGS_MAX_LENGTH,
|
|
676
683
|
DD_TRACING_ENABLED,
|
|
677
684
|
DD_VERSION,
|
|
685
|
+
DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED,
|
|
678
686
|
OTEL_METRICS_EXPORTER,
|
|
679
687
|
OTEL_PROPAGATORS,
|
|
680
688
|
OTEL_RESOURCE_ATTRIBUTES,
|
|
@@ -696,7 +704,7 @@ class Config {
|
|
|
696
704
|
DD_API_SECURITY_ENABLED && isTrue(DD_API_SECURITY_ENABLED),
|
|
697
705
|
DD_EXPERIMENTAL_API_SECURITY_ENABLED && isTrue(DD_EXPERIMENTAL_API_SECURITY_ENABLED)
|
|
698
706
|
))
|
|
699
|
-
this.
|
|
707
|
+
this._setValue(env, 'appsec.apiSecurity.sampleDelay', maybeFloat(DD_API_SECURITY_SAMPLE_DELAY))
|
|
700
708
|
this._setValue(env, 'appsec.blockedTemplateGraphql', maybeFile(DD_APPSEC_GRAPHQL_BLOCKED_TEMPLATE_JSON))
|
|
701
709
|
this._setValue(env, 'appsec.blockedTemplateHtml', maybeFile(DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML))
|
|
702
710
|
this._envUnprocessed['appsec.blockedTemplateHtml'] = DD_APPSEC_HTTP_BLOCKED_TEMPLATE_HTML
|
|
@@ -728,6 +736,7 @@ class Config {
|
|
|
728
736
|
this._setValue(env, 'baggageMaxItems', DD_TRACE_BAGGAGE_MAX_ITEMS)
|
|
729
737
|
this._setBoolean(env, 'clientIpEnabled', DD_TRACE_CLIENT_IP_ENABLED)
|
|
730
738
|
this._setString(env, 'clientIpHeader', DD_TRACE_CLIENT_IP_HEADER)
|
|
739
|
+
this._setBoolean(env, 'crashtracking.enabled', DD_CRASHTRACKING_ENABLED)
|
|
731
740
|
this._setBoolean(env, 'codeOriginForSpans.enabled', DD_CODE_ORIGIN_FOR_SPANS_ENABLED)
|
|
732
741
|
this._setString(env, 'dbmPropagationMode', DD_DBM_PROPAGATION_MODE)
|
|
733
742
|
this._setString(env, 'dogstatsd.hostname', DD_DOGSTATSD_HOSTNAME)
|
|
@@ -766,6 +775,10 @@ class Config {
|
|
|
766
775
|
this._setArray(env, 'injectionEnabled', DD_INJECTION_ENABLED)
|
|
767
776
|
this._setBoolean(env, 'isAzureFunction', getIsAzureFunction())
|
|
768
777
|
this._setBoolean(env, 'isGCPFunction', getIsGCPFunction())
|
|
778
|
+
this._setValue(env, 'langchain.spanCharLimit', maybeInt(DD_LANGCHAIN_SPAN_CHAR_LIMIT))
|
|
779
|
+
this._setValue(
|
|
780
|
+
env, 'langchain.spanPromptCompletionSampleRate', maybeFloat(DD_LANGCHAIN_SPAN_PROMPT_COMPLETION_SAMPLE_RATE)
|
|
781
|
+
)
|
|
769
782
|
this._setBoolean(env, 'legacyBaggageEnabled', DD_TRACE_LEGACY_BAGGAGE_ENABLED)
|
|
770
783
|
this._setBoolean(env, 'llmobs.agentlessEnabled', DD_LLMOBS_AGENTLESS_ENABLED)
|
|
771
784
|
this._setBoolean(env, 'llmobs.enabled', DD_LLMOBS_ENABLED)
|
|
@@ -862,6 +875,7 @@ class Config {
|
|
|
862
875
|
: !!OTEL_PROPAGATORS)
|
|
863
876
|
this._setBoolean(env, 'tracing', DD_TRACING_ENABLED)
|
|
864
877
|
this._setString(env, 'version', DD_VERSION || tags.version)
|
|
878
|
+
this._setBoolean(env, 'inferredProxyServicesEnabled', DD_TRACE_INFERRED_PROXY_SERVICES_ENABLED)
|
|
865
879
|
}
|
|
866
880
|
|
|
867
881
|
_applyOptions (options) {
|
|
@@ -874,7 +888,6 @@ class Config {
|
|
|
874
888
|
tagger.add(tags, options.tags)
|
|
875
889
|
|
|
876
890
|
this._setBoolean(opts, 'appsec.apiSecurity.enabled', options.appsec.apiSecurity?.enabled)
|
|
877
|
-
this._setUnit(opts, 'appsec.apiSecurity.requestSampling', options.appsec.apiSecurity?.requestSampling)
|
|
878
891
|
this._setValue(opts, 'appsec.blockedTemplateGraphql', maybeFile(options.appsec.blockedTemplateGraphql))
|
|
879
892
|
this._setValue(opts, 'appsec.blockedTemplateHtml', maybeFile(options.appsec.blockedTemplateHtml))
|
|
880
893
|
this._optsUnprocessed['appsec.blockedTemplateHtml'] = options.appsec.blockedTemplateHtml
|
|
@@ -980,6 +993,7 @@ class Config {
|
|
|
980
993
|
this._setBoolean(opts, 'traceId128BitGenerationEnabled', options.traceId128BitGenerationEnabled)
|
|
981
994
|
this._setBoolean(opts, 'traceId128BitLoggingEnabled', options.traceId128BitLoggingEnabled)
|
|
982
995
|
this._setString(opts, 'version', options.version || tags.version)
|
|
996
|
+
this._setBoolean(opts, 'inferredProxyServicesEnabled', options.inferredProxyServicesEnabled)
|
|
983
997
|
|
|
984
998
|
// For LLMObs, we want the environment variable to take precedence over the options.
|
|
985
999
|
// This is reliant on environment config being set before options.
|
|
@@ -1134,6 +1148,9 @@ class Config {
|
|
|
1134
1148
|
if (iastEnabled || ['auto', 'true'].includes(profilingEnabled) || injectionIncludesProfiler) {
|
|
1135
1149
|
this._setBoolean(calc, 'telemetry.logCollection', true)
|
|
1136
1150
|
}
|
|
1151
|
+
if (this._env.injectionEnabled?.length > 0) {
|
|
1152
|
+
this._setBoolean(calc, 'crashtracking.enabled', true)
|
|
1153
|
+
}
|
|
1137
1154
|
}
|
|
1138
1155
|
|
|
1139
1156
|
_applyRemote (options) {
|
|
@@ -46,5 +46,10 @@ module.exports = {
|
|
|
46
46
|
SCHEMA_OPERATION: 'schema.operation',
|
|
47
47
|
SCHEMA_NAME: 'schema.name',
|
|
48
48
|
GRPC_CLIENT_ERROR_STATUSES: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
|
|
49
|
-
GRPC_SERVER_ERROR_STATUSES: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
|
|
49
|
+
GRPC_SERVER_ERROR_STATUSES: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
|
|
50
|
+
S3_PTR_KIND: 'aws.s3.object',
|
|
51
|
+
SPAN_POINTER_DIRECTION: Object.freeze({
|
|
52
|
+
UPSTREAM: 'u',
|
|
53
|
+
DOWNSTREAM: 'd'
|
|
54
|
+
})
|
|
50
55
|
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
// Load binding first to not import other modules if it throws
|
|
4
|
+
const libdatadog = require('@datadog/libdatadog')
|
|
5
|
+
const binding = libdatadog.load('crashtracker')
|
|
6
|
+
|
|
7
|
+
const log = require('../log')
|
|
8
|
+
const { URL } = require('url')
|
|
9
|
+
const pkg = require('../../../../package.json')
|
|
10
|
+
|
|
11
|
+
class Crashtracker {
|
|
12
|
+
constructor () {
|
|
13
|
+
this._started = false
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
configure (config) {
|
|
17
|
+
if (!this._started) return
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
binding.updateConfig(this._getConfig(config))
|
|
21
|
+
binding.updateMetadata(this._getMetadata(config))
|
|
22
|
+
} catch (e) {
|
|
23
|
+
log.error(e)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
start (config) {
|
|
28
|
+
if (this._started) return this.configure(config)
|
|
29
|
+
|
|
30
|
+
this._started = true
|
|
31
|
+
|
|
32
|
+
try {
|
|
33
|
+
binding.init(
|
|
34
|
+
this._getConfig(config),
|
|
35
|
+
this._getReceiverConfig(config),
|
|
36
|
+
this._getMetadata(config)
|
|
37
|
+
)
|
|
38
|
+
} catch (e) {
|
|
39
|
+
log.error(e)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// TODO: Send only configured values when defaults are fixed.
|
|
44
|
+
_getConfig (config) {
|
|
45
|
+
const { hostname = '127.0.0.1', port = 8126 } = config
|
|
46
|
+
const url = config.url || new URL(`http://${hostname}:${port}`)
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
additional_files: [],
|
|
50
|
+
create_alt_stack: true,
|
|
51
|
+
use_alt_stack: true,
|
|
52
|
+
endpoint: {
|
|
53
|
+
// TODO: Use the string directly when deserialization is fixed.
|
|
54
|
+
url: {
|
|
55
|
+
scheme: url.protocol.slice(0, -1),
|
|
56
|
+
authority: url.protocol === 'unix:'
|
|
57
|
+
? Buffer.from(url.pathname).toString('hex')
|
|
58
|
+
: url.host,
|
|
59
|
+
path_and_query: ''
|
|
60
|
+
},
|
|
61
|
+
timeout_ms: 3000
|
|
62
|
+
},
|
|
63
|
+
timeout_ms: 5000,
|
|
64
|
+
// TODO: Use `EnabledWithSymbolsInReceiver` instead for Linux when fixed.
|
|
65
|
+
resolve_frames: 'EnabledWithInprocessSymbols'
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
_getMetadata (config) {
|
|
70
|
+
const tags = Object.keys(config.tags).map(key => `${key}:${config.tags[key]}`)
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
library_name: pkg.name,
|
|
74
|
+
library_version: pkg.version,
|
|
75
|
+
family: 'nodejs',
|
|
76
|
+
tags: [
|
|
77
|
+
...tags,
|
|
78
|
+
'is_crash:true',
|
|
79
|
+
'language:javascript',
|
|
80
|
+
`library_version:${pkg.version}`,
|
|
81
|
+
'runtime:nodejs',
|
|
82
|
+
'severity:crash'
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
_getReceiverConfig () {
|
|
88
|
+
return {
|
|
89
|
+
args: [],
|
|
90
|
+
env: [],
|
|
91
|
+
path_to_receiver_binary: libdatadog.find('crashtracker-receiver', true),
|
|
92
|
+
stderr_filename: null,
|
|
93
|
+
stdout_filename: null
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
module.exports = new Crashtracker()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { isMainThread } = require('worker_threads')
|
|
4
|
+
const log = require('../log')
|
|
5
|
+
|
|
6
|
+
if (isMainThread) {
|
|
7
|
+
try {
|
|
8
|
+
module.exports = require('./crashtracker')
|
|
9
|
+
} catch (e) {
|
|
10
|
+
log.warn(e.message)
|
|
11
|
+
module.exports = require('./noop')
|
|
12
|
+
}
|
|
13
|
+
} else {
|
|
14
|
+
module.exports = require('./noop')
|
|
15
|
+
}
|
|
@@ -6,6 +6,8 @@ const { DROPPED_IO_COLLECTION_ERROR } = require('../../constants/tags')
|
|
|
6
6
|
const BaseWriter = require('../base')
|
|
7
7
|
const logger = require('../../../log')
|
|
8
8
|
|
|
9
|
+
const tracerVersion = require('../../../../../../package.json').version
|
|
10
|
+
|
|
9
11
|
class LLMObsSpanWriter extends BaseWriter {
|
|
10
12
|
constructor (options) {
|
|
11
13
|
super({
|
|
@@ -32,6 +34,7 @@ class LLMObsSpanWriter extends BaseWriter {
|
|
|
32
34
|
makePayload (events) {
|
|
33
35
|
return {
|
|
34
36
|
'_dd.stage': 'raw',
|
|
37
|
+
'_dd.tracer_version': tracerVersion,
|
|
35
38
|
event_type: this._eventType,
|
|
36
39
|
spans: events
|
|
37
40
|
}
|
|
@@ -4,6 +4,7 @@ const coalesce = require('koalas')
|
|
|
4
4
|
const { isTrue } = require('../util')
|
|
5
5
|
const { debugChannel, infoChannel, warnChannel, errorChannel } = require('./channels')
|
|
6
6
|
const logWriter = require('./writer')
|
|
7
|
+
const { Log } = require('./log')
|
|
7
8
|
|
|
8
9
|
const memoize = func => {
|
|
9
10
|
const cache = {}
|
|
@@ -18,10 +19,6 @@ const memoize = func => {
|
|
|
18
19
|
return memoized
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
function processMsg (msg) {
|
|
22
|
-
return typeof msg === 'function' ? msg() : msg
|
|
23
|
-
}
|
|
24
|
-
|
|
25
22
|
const config = {
|
|
26
23
|
enabled: false,
|
|
27
24
|
logger: undefined,
|
|
@@ -52,37 +49,37 @@ const log = {
|
|
|
52
49
|
reset () {
|
|
53
50
|
logWriter.reset()
|
|
54
51
|
this._deprecate = memoize((code, message) => {
|
|
55
|
-
errorChannel.publish(message)
|
|
52
|
+
errorChannel.publish(Log.parse(message))
|
|
56
53
|
return true
|
|
57
54
|
})
|
|
58
55
|
|
|
59
56
|
return this
|
|
60
57
|
},
|
|
61
58
|
|
|
62
|
-
debug (
|
|
59
|
+
debug (...args) {
|
|
63
60
|
if (debugChannel.hasSubscribers) {
|
|
64
|
-
debugChannel.publish(
|
|
61
|
+
debugChannel.publish(Log.parse(...args))
|
|
65
62
|
}
|
|
66
63
|
return this
|
|
67
64
|
},
|
|
68
65
|
|
|
69
|
-
info (
|
|
66
|
+
info (...args) {
|
|
70
67
|
if (infoChannel.hasSubscribers) {
|
|
71
|
-
infoChannel.publish(
|
|
68
|
+
infoChannel.publish(Log.parse(...args))
|
|
72
69
|
}
|
|
73
70
|
return this
|
|
74
71
|
},
|
|
75
72
|
|
|
76
|
-
warn (
|
|
73
|
+
warn (...args) {
|
|
77
74
|
if (warnChannel.hasSubscribers) {
|
|
78
|
-
warnChannel.publish(
|
|
75
|
+
warnChannel.publish(Log.parse(...args))
|
|
79
76
|
}
|
|
80
77
|
return this
|
|
81
78
|
},
|
|
82
79
|
|
|
83
|
-
error (
|
|
80
|
+
error (...args) {
|
|
84
81
|
if (errorChannel.hasSubscribers) {
|
|
85
|
-
errorChannel.publish(
|
|
82
|
+
errorChannel.publish(Log.parse(...args))
|
|
86
83
|
}
|
|
87
84
|
return this
|
|
88
85
|
},
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { format } = require('util')
|
|
4
|
+
|
|
5
|
+
class Log {
|
|
6
|
+
constructor (message, args, cause, delegate) {
|
|
7
|
+
this.message = message
|
|
8
|
+
this.args = args
|
|
9
|
+
this.cause = cause
|
|
10
|
+
this.delegate = delegate
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
get formatted () {
|
|
14
|
+
const { message, args } = this
|
|
15
|
+
|
|
16
|
+
let formatted = message
|
|
17
|
+
if (message && args && args.length) {
|
|
18
|
+
formatted = format(message, ...args)
|
|
19
|
+
}
|
|
20
|
+
return formatted
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static parse (...args) {
|
|
24
|
+
let message, cause, delegate
|
|
25
|
+
|
|
26
|
+
const lastArg = args[args.length - 1]
|
|
27
|
+
if (lastArg && typeof lastArg === 'object' && lastArg.stack) { // lastArg instanceof Error?
|
|
28
|
+
cause = args.pop()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const firstArg = args.shift()
|
|
32
|
+
if (firstArg) {
|
|
33
|
+
if (typeof firstArg === 'string') {
|
|
34
|
+
message = firstArg
|
|
35
|
+
} else if (typeof firstArg === 'object') {
|
|
36
|
+
message = String(firstArg.message || firstArg)
|
|
37
|
+
} else if (typeof firstArg === 'function') {
|
|
38
|
+
delegate = firstArg
|
|
39
|
+
} else {
|
|
40
|
+
message = String(firstArg)
|
|
41
|
+
}
|
|
42
|
+
} else if (!cause) {
|
|
43
|
+
message = String(firstArg)
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return new Log(message, args, cause, delegate)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = {
|
|
51
|
+
Log
|
|
52
|
+
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { storage } = require('../../../datadog-core')
|
|
4
4
|
const { LogChannel } = require('./channels')
|
|
5
|
+
const { Log } = require('./log')
|
|
5
6
|
const defaultLogger = {
|
|
6
7
|
debug: msg => console.debug(msg), /* eslint-disable-line no-console */
|
|
7
8
|
info: msg => console.info(msg), /* eslint-disable-line no-console */
|
|
@@ -22,7 +23,7 @@ function withNoop (fn) {
|
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
function unsubscribeAll () {
|
|
25
|
-
logChannel.unsubscribe({ debug, info, warn, error })
|
|
26
|
+
logChannel.unsubscribe({ debug: onDebug, info: onInfo, warn: onWarn, error: onError })
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
function toggleSubscription (enable, level) {
|
|
@@ -30,7 +31,7 @@ function toggleSubscription (enable, level) {
|
|
|
30
31
|
|
|
31
32
|
if (enable) {
|
|
32
33
|
logChannel = new LogChannel(level)
|
|
33
|
-
logChannel.subscribe({ debug, info, warn, error })
|
|
34
|
+
logChannel.subscribe({ debug: onDebug, info: onInfo, warn: onWarn, error: onError })
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
|
|
@@ -51,32 +52,62 @@ function reset () {
|
|
|
51
52
|
toggleSubscription(false)
|
|
52
53
|
}
|
|
53
54
|
|
|
54
|
-
function
|
|
55
|
-
if (typeof err
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
function getErrorLog (err) {
|
|
56
|
+
if (err && typeof err.delegate === 'function') {
|
|
57
|
+
const result = err.delegate()
|
|
58
|
+
return Array.isArray(result) ? Log.parse(...result) : Log.parse(result)
|
|
59
|
+
} else {
|
|
60
|
+
return err
|
|
59
61
|
}
|
|
62
|
+
}
|
|
60
63
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
function onError (err) {
|
|
65
|
+
const { formatted, cause } = getErrorLog(err)
|
|
66
|
+
|
|
67
|
+
// calling twice logger.error() because Error cause is only available in nodejs v16.9.0
|
|
68
|
+
// TODO: replace it with Error(message, { cause }) when cause has broad support
|
|
69
|
+
if (formatted) withNoop(() => logger.error(new Error(formatted)))
|
|
70
|
+
if (cause) withNoop(() => logger.error(cause))
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function onWarn (log) {
|
|
74
|
+
const { formatted, cause } = getErrorLog(log)
|
|
75
|
+
if (formatted) withNoop(() => logger.warn(formatted))
|
|
76
|
+
if (cause) withNoop(() => logger.warn(cause))
|
|
77
|
+
}
|
|
64
78
|
|
|
65
|
-
|
|
79
|
+
function onInfo (log) {
|
|
80
|
+
const { formatted, cause } = getErrorLog(log)
|
|
81
|
+
if (formatted) withNoop(() => logger.info(formatted))
|
|
82
|
+
if (cause) withNoop(() => logger.info(cause))
|
|
66
83
|
}
|
|
67
84
|
|
|
68
|
-
function
|
|
69
|
-
|
|
70
|
-
withNoop(() => logger.
|
|
85
|
+
function onDebug (log) {
|
|
86
|
+
const { formatted, cause } = getErrorLog(log)
|
|
87
|
+
if (formatted) withNoop(() => logger.debug(formatted))
|
|
88
|
+
if (cause) withNoop(() => logger.debug(cause))
|
|
71
89
|
}
|
|
72
90
|
|
|
73
|
-
function
|
|
74
|
-
|
|
75
|
-
|
|
91
|
+
function error (...args) {
|
|
92
|
+
onError(Log.parse(...args))
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function warn (...args) {
|
|
96
|
+
const log = Log.parse(...args)
|
|
97
|
+
if (!logger.warn) return onDebug(log)
|
|
98
|
+
|
|
99
|
+
onWarn(log)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function info (...args) {
|
|
103
|
+
const log = Log.parse(...args)
|
|
104
|
+
if (!logger.info) return onDebug(log)
|
|
105
|
+
|
|
106
|
+
onInfo(log)
|
|
76
107
|
}
|
|
77
108
|
|
|
78
|
-
function debug (
|
|
79
|
-
|
|
109
|
+
function debug (...args) {
|
|
110
|
+
onDebug(Log.parse(...args))
|
|
80
111
|
}
|
|
81
112
|
|
|
82
113
|
module.exports = { use, toggle, reset, error, warn, info, debug }
|
|
@@ -14,6 +14,7 @@ const { SERVICE_NAME, RESOURCE_NAME } = require('../../../../ext/tags')
|
|
|
14
14
|
const kinds = require('../../../../ext/kinds')
|
|
15
15
|
|
|
16
16
|
const SpanContext = require('./span_context')
|
|
17
|
+
const id = require('../id')
|
|
17
18
|
|
|
18
19
|
// The one built into OTel rounds so we lose sub-millisecond precision.
|
|
19
20
|
function hrTimeToMilliseconds (time) {
|
|
@@ -217,6 +218,20 @@ class Span {
|
|
|
217
218
|
return this
|
|
218
219
|
}
|
|
219
220
|
|
|
221
|
+
addSpanPointer (ptrKind, ptrDir, ptrHash) {
|
|
222
|
+
const zeroContext = new SpanContext({
|
|
223
|
+
traceId: id('0'),
|
|
224
|
+
spanId: id('0')
|
|
225
|
+
})
|
|
226
|
+
const attributes = {
|
|
227
|
+
'ptr.kind': ptrKind,
|
|
228
|
+
'ptr.dir': ptrDir,
|
|
229
|
+
'ptr.hash': ptrHash,
|
|
230
|
+
'link.kind': 'span-pointer'
|
|
231
|
+
}
|
|
232
|
+
return this.addLink(zeroContext, attributes)
|
|
233
|
+
}
|
|
234
|
+
|
|
220
235
|
setStatus ({ code, message }) {
|
|
221
236
|
if (!this.ended && !this._hasStatus && code) {
|
|
222
237
|
this._hasStatus = true
|