dd-trace 5.24.0 → 5.26.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 +3 -0
- package/index.d.ts +345 -8
- package/init.js +60 -47
- package/package.json +16 -7
- package/packages/datadog-code-origin/index.js +4 -4
- package/packages/datadog-core/index.js +1 -3
- package/packages/datadog-core/src/storage.js +21 -0
- package/packages/datadog-core/src/utils/src/parse-tags.js +33 -0
- package/packages/datadog-esbuild/index.js +4 -2
- package/packages/datadog-instrumentations/src/amqplib.js +65 -5
- package/packages/datadog-instrumentations/src/child_process.js +135 -27
- 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/helpers/register.js +9 -0
- package/packages/datadog-instrumentations/src/jest.js +6 -2
- package/packages/datadog-instrumentations/src/kafkajs.js +123 -63
- package/packages/datadog-instrumentations/src/mocha/utils.js +2 -2
- package/packages/datadog-instrumentations/src/multer.js +37 -0
- package/packages/datadog-instrumentations/src/openai.js +2 -2
- package/packages/datadog-instrumentations/src/pug.js +23 -0
- package/packages/datadog-instrumentations/src/router.js +2 -3
- package/packages/datadog-instrumentations/src/url.js +84 -0
- package/packages/datadog-instrumentations/src/utils/src/extract-package-and-module-path.js +7 -4
- package/packages/datadog-plugin-amqplib/src/consumer.js +6 -5
- package/packages/datadog-plugin-aws-sdk/src/base.js +5 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +10 -7
- package/packages/datadog-plugin-aws-sdk/src/services/s3.js +35 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +11 -9
- 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-fastify/src/code_origin.js +2 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +10 -2
- package/packages/datadog-plugin-google-cloud-pubsub/src/producer.js +8 -0
- package/packages/datadog-plugin-grpc/src/client.js +3 -0
- package/packages/datadog-plugin-grpc/src/server.js +5 -1
- package/packages/datadog-plugin-http/src/client.js +42 -1
- package/packages/datadog-plugin-http2/src/client.js +26 -1
- package/packages/datadog-plugin-jest/src/index.js +2 -1
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +6 -3
- package/packages/datadog-plugin-kafkajs/src/consumer.js +10 -5
- package/packages/datadog-plugin-kafkajs/src/producer.js +10 -4
- package/packages/datadog-plugin-mocha/src/index.js +5 -2
- package/packages/datadog-plugin-moleculer/src/server.js +2 -2
- package/packages/datadog-plugin-openai/src/index.js +9 -1015
- package/packages/datadog-plugin-openai/src/tracing.js +1023 -0
- package/packages/datadog-plugin-rhea/src/consumer.js +2 -1
- package/packages/datadog-plugin-vitest/src/index.js +2 -1
- package/packages/dd-trace/src/appsec/addresses.js +2 -0
- package/packages/dd-trace/src/appsec/api_security_sampler.js +50 -27
- package/packages/dd-trace/src/appsec/channels.js +3 -1
- 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/taint-tracking/plugin.js +55 -7
- 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/iast/vulnerability-reporter.js +4 -2
- package/packages/dd-trace/src/appsec/index.js +9 -6
- package/packages/dd-trace/src/appsec/rasp/command_injection.js +49 -0
- package/packages/dd-trace/src/appsec/rasp/index.js +3 -0
- package/packages/dd-trace/src/appsec/rasp/ssrf.js +4 -3
- package/packages/dd-trace/src/appsec/rasp/utils.js +3 -2
- package/packages/dd-trace/src/appsec/recommended.json +354 -158
- package/packages/dd-trace/src/appsec/remote_config/capabilities.js +2 -1
- package/packages/dd-trace/src/appsec/remote_config/index.js +2 -7
- package/packages/dd-trace/src/appsec/reporter.js +6 -4
- package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -3
- package/packages/dd-trace/src/appsec/waf/waf_manager.js +4 -0
- package/packages/dd-trace/src/azure_metadata.js +120 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/index.js +97 -0
- package/packages/dd-trace/src/ci-visibility/dynamic-instrumentation/worker/index.js +90 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agent-proxy/index.js +19 -1
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +53 -0
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/index.js +8 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +43 -0
- package/packages/dd-trace/src/config.js +88 -10
- package/packages/dd-trace/src/constants.js +8 -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/datastreams/pathway.js +1 -0
- package/packages/dd-trace/src/debugger/devtools_client/index.js +9 -13
- package/packages/dd-trace/src/debugger/devtools_client/send.js +15 -1
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/collector.js +57 -23
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/index.js +12 -2
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +31 -20
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/symbols.js +6 -0
- package/packages/dd-trace/src/debugger/devtools_client/state.js +11 -2
- package/packages/dd-trace/src/debugger/index.js +10 -3
- package/packages/dd-trace/src/llmobs/constants/tags.js +34 -0
- package/packages/dd-trace/src/llmobs/constants/text.js +6 -0
- package/packages/dd-trace/src/llmobs/constants/writers.js +13 -0
- package/packages/dd-trace/src/llmobs/index.js +103 -0
- package/packages/dd-trace/src/llmobs/noop.js +82 -0
- package/packages/dd-trace/src/llmobs/plugins/base.js +65 -0
- package/packages/dd-trace/src/llmobs/plugins/openai.js +205 -0
- package/packages/dd-trace/src/llmobs/sdk.js +377 -0
- package/packages/dd-trace/src/llmobs/span_processor.js +195 -0
- package/packages/dd-trace/src/llmobs/storage.js +7 -0
- package/packages/dd-trace/src/llmobs/tagger.js +322 -0
- package/packages/dd-trace/src/llmobs/util.js +176 -0
- package/packages/dd-trace/src/llmobs/writers/base.js +111 -0
- package/packages/dd-trace/src/llmobs/writers/evaluations.js +29 -0
- package/packages/dd-trace/src/llmobs/writers/spans/agentProxy.js +23 -0
- package/packages/dd-trace/src/llmobs/writers/spans/agentless.js +17 -0
- package/packages/dd-trace/src/llmobs/writers/spans/base.js +52 -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/proxy.js +3 -0
- package/packages/dd-trace/src/noop/span.js +4 -0
- package/packages/dd-trace/src/opentelemetry/span.js +16 -1
- package/packages/dd-trace/src/opentelemetry/tracer.js +1 -0
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +106 -32
- package/packages/dd-trace/src/opentracing/span.js +26 -0
- package/packages/dd-trace/src/opentracing/span_context.js +1 -0
- package/packages/dd-trace/src/opentracing/tracer.js +8 -1
- package/packages/dd-trace/src/payload-tagging/config/aws.json +71 -3
- package/packages/dd-trace/src/plugins/outbound.js +9 -0
- package/packages/dd-trace/src/plugins/tracing.js +3 -3
- 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/priority_sampler.js +16 -0
- package/packages/dd-trace/src/profiling/config.js +3 -1
- package/packages/dd-trace/src/profiling/exporters/agent.js +7 -5
- package/packages/dd-trace/src/profiling/profilers/wall.js +2 -1
- package/packages/dd-trace/src/proxy.js +13 -1
- package/packages/dd-trace/src/span_processor.js +5 -0
- package/packages/dd-trace/src/telemetry/index.js +11 -1
- 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
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const request = require('../../exporters/common/request')
|
|
4
|
+
const { URL, format } = require('url')
|
|
5
|
+
|
|
6
|
+
const logger = require('../../log')
|
|
7
|
+
|
|
8
|
+
const { encodeUnicode } = require('../util')
|
|
9
|
+
const log = require('../../log')
|
|
10
|
+
|
|
11
|
+
class BaseLLMObsWriter {
|
|
12
|
+
constructor ({ interval, timeout, endpoint, intake, eventType, protocol, port }) {
|
|
13
|
+
this._interval = interval || 1000 // 1s
|
|
14
|
+
this._timeout = timeout || 5000 // 5s
|
|
15
|
+
this._eventType = eventType
|
|
16
|
+
|
|
17
|
+
this._buffer = []
|
|
18
|
+
this._bufferLimit = 1000
|
|
19
|
+
this._bufferSize = 0
|
|
20
|
+
|
|
21
|
+
this._url = new URL(format({
|
|
22
|
+
protocol: protocol || 'https:',
|
|
23
|
+
hostname: intake,
|
|
24
|
+
port: port || 443,
|
|
25
|
+
pathname: endpoint
|
|
26
|
+
}))
|
|
27
|
+
|
|
28
|
+
this._headers = {
|
|
29
|
+
'Content-Type': 'application/json'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
this._periodic = setInterval(() => {
|
|
33
|
+
this.flush()
|
|
34
|
+
}, this._interval).unref()
|
|
35
|
+
|
|
36
|
+
process.once('beforeExit', () => {
|
|
37
|
+
this.destroy()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
this._destroyed = false
|
|
41
|
+
|
|
42
|
+
logger.debug(`Started ${this.constructor.name} to ${this._url}`)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
append (event, byteLength) {
|
|
46
|
+
if (this._buffer.length >= this._bufferLimit) {
|
|
47
|
+
logger.warn(`${this.constructor.name} event buffer full (limit is ${this._bufferLimit}), dropping event`)
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this._bufferSize += byteLength || Buffer.from(JSON.stringify(event)).byteLength
|
|
52
|
+
this._buffer.push(event)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
flush () {
|
|
56
|
+
if (this._buffer.length === 0) {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const events = this._buffer
|
|
61
|
+
this._buffer = []
|
|
62
|
+
this._bufferSize = 0
|
|
63
|
+
const payload = this._encode(this.makePayload(events))
|
|
64
|
+
|
|
65
|
+
const options = {
|
|
66
|
+
headers: this._headers,
|
|
67
|
+
method: 'POST',
|
|
68
|
+
url: this._url,
|
|
69
|
+
timeout: this._timeout
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
log.debug(`Encoded LLMObs payload: ${payload}`)
|
|
73
|
+
|
|
74
|
+
request(payload, options, (err, resp, code) => {
|
|
75
|
+
if (err) {
|
|
76
|
+
logger.error(
|
|
77
|
+
`Error sending ${events.length} LLMObs ${this._eventType} events to ${this._url}: ${err.message}`
|
|
78
|
+
)
|
|
79
|
+
} else if (code >= 300) {
|
|
80
|
+
logger.error(
|
|
81
|
+
`Error sending ${events.length} LLMObs ${this._eventType} events to ${this._url}: ${code}`
|
|
82
|
+
)
|
|
83
|
+
} else {
|
|
84
|
+
logger.debug(`Sent ${events.length} LLMObs ${this._eventType} events to ${this._url}`)
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
makePayload (events) {}
|
|
90
|
+
|
|
91
|
+
destroy () {
|
|
92
|
+
if (!this._destroyed) {
|
|
93
|
+
logger.debug(`Stopping ${this.constructor.name}`)
|
|
94
|
+
clearInterval(this._periodic)
|
|
95
|
+
process.removeListener('beforeExit', this.destroy)
|
|
96
|
+
this.flush()
|
|
97
|
+
this._destroyed = true
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
_encode (payload) {
|
|
102
|
+
return JSON.stringify(payload, (key, value) => {
|
|
103
|
+
if (typeof value === 'string') {
|
|
104
|
+
return encodeUnicode(value) // serialize unicode characters
|
|
105
|
+
}
|
|
106
|
+
return value
|
|
107
|
+
}).replace(/\\\\u/g, '\\u') // remove double escaping
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
module.exports = BaseLLMObsWriter
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { AGENTLESS_EVALULATIONS_ENDPOINT } = require('../constants/writers')
|
|
4
|
+
const BaseWriter = require('./base')
|
|
5
|
+
|
|
6
|
+
class LLMObsEvalMetricsWriter extends BaseWriter {
|
|
7
|
+
constructor (config) {
|
|
8
|
+
super({
|
|
9
|
+
endpoint: AGENTLESS_EVALULATIONS_ENDPOINT,
|
|
10
|
+
intake: `api.${config.site}`,
|
|
11
|
+
eventType: 'evaluation_metric'
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
this._headers['DD-API-KEY'] = config.apiKey
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
makePayload (events) {
|
|
18
|
+
return {
|
|
19
|
+
data: {
|
|
20
|
+
type: this._eventType,
|
|
21
|
+
attributes: {
|
|
22
|
+
metrics: events
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
module.exports = LLMObsEvalMetricsWriter
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const {
|
|
4
|
+
EVP_SUBDOMAIN_HEADER_NAME,
|
|
5
|
+
EVP_SUBDOMAIN_HEADER_VALUE,
|
|
6
|
+
EVP_PROXY_AGENT_ENDPOINT
|
|
7
|
+
} = require('../../constants/writers')
|
|
8
|
+
const LLMObsBaseSpanWriter = require('./base')
|
|
9
|
+
|
|
10
|
+
class LLMObsAgentProxySpanWriter extends LLMObsBaseSpanWriter {
|
|
11
|
+
constructor (config) {
|
|
12
|
+
super({
|
|
13
|
+
intake: config.hostname || 'localhost',
|
|
14
|
+
protocol: 'http:',
|
|
15
|
+
endpoint: EVP_PROXY_AGENT_ENDPOINT,
|
|
16
|
+
port: config.port
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
this._headers[EVP_SUBDOMAIN_HEADER_NAME] = EVP_SUBDOMAIN_HEADER_VALUE
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = LLMObsAgentProxySpanWriter
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { AGENTLESS_SPANS_ENDPOINT } = require('../../constants/writers')
|
|
4
|
+
const LLMObsBaseSpanWriter = require('./base')
|
|
5
|
+
|
|
6
|
+
class LLMObsAgentlessSpanWriter extends LLMObsBaseSpanWriter {
|
|
7
|
+
constructor (config) {
|
|
8
|
+
super({
|
|
9
|
+
intake: `llmobs-intake.${config.site}`,
|
|
10
|
+
endpoint: AGENTLESS_SPANS_ENDPOINT
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
this._headers['DD-API-KEY'] = config.apiKey
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = LLMObsAgentlessSpanWriter
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { EVP_EVENT_SIZE_LIMIT, EVP_PAYLOAD_SIZE_LIMIT } = require('../../constants/writers')
|
|
4
|
+
const { DROPPED_VALUE_TEXT } = require('../../constants/text')
|
|
5
|
+
const { DROPPED_IO_COLLECTION_ERROR } = require('../../constants/tags')
|
|
6
|
+
const BaseWriter = require('../base')
|
|
7
|
+
const logger = require('../../../log')
|
|
8
|
+
|
|
9
|
+
const tracerVersion = require('../../../../../../package.json').version
|
|
10
|
+
|
|
11
|
+
class LLMObsSpanWriter extends BaseWriter {
|
|
12
|
+
constructor (options) {
|
|
13
|
+
super({
|
|
14
|
+
...options,
|
|
15
|
+
eventType: 'span'
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
append (event) {
|
|
20
|
+
const eventSizeBytes = Buffer.from(JSON.stringify(event)).byteLength
|
|
21
|
+
if (eventSizeBytes > EVP_EVENT_SIZE_LIMIT) {
|
|
22
|
+
logger.warn(`Dropping event input/output because its size (${eventSizeBytes}) exceeds the 1MB event size limit`)
|
|
23
|
+
event = this._truncateSpanEvent(event)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (this._bufferSize + eventSizeBytes > EVP_PAYLOAD_SIZE_LIMIT) {
|
|
27
|
+
logger.debug('Flusing queue because queing next event will exceed EvP payload limit')
|
|
28
|
+
this.flush()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
super.append(event, eventSizeBytes)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
makePayload (events) {
|
|
35
|
+
return {
|
|
36
|
+
'_dd.stage': 'raw',
|
|
37
|
+
'_dd.tracer_version': tracerVersion,
|
|
38
|
+
event_type: this._eventType,
|
|
39
|
+
spans: events
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
_truncateSpanEvent (event) {
|
|
44
|
+
event.meta.input = { value: DROPPED_VALUE_TEXT }
|
|
45
|
+
event.meta.output = { value: DROPPED_VALUE_TEXT }
|
|
46
|
+
|
|
47
|
+
event.collection_errors = [DROPPED_IO_COLLECTION_ERROR]
|
|
48
|
+
return event
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = LLMObsSpanWriter
|
|
@@ -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 }
|
|
@@ -3,16 +3,19 @@
|
|
|
3
3
|
const NoopTracer = require('./tracer')
|
|
4
4
|
const NoopAppsecSdk = require('../appsec/sdk/noop')
|
|
5
5
|
const NoopDogStatsDClient = require('./dogstatsd')
|
|
6
|
+
const NoopLLMObsSDK = require('../llmobs/noop')
|
|
6
7
|
|
|
7
8
|
const noop = new NoopTracer()
|
|
8
9
|
const noopAppsec = new NoopAppsecSdk()
|
|
9
10
|
const noopDogStatsDClient = new NoopDogStatsDClient()
|
|
11
|
+
const noopLLMObs = new NoopLLMObsSDK(noop)
|
|
10
12
|
|
|
11
13
|
class Tracer {
|
|
12
14
|
constructor () {
|
|
13
15
|
this._tracer = noop
|
|
14
16
|
this.appsec = noopAppsec
|
|
15
17
|
this.dogstatsd = noopDogStatsDClient
|
|
18
|
+
this.llmobs = noopLLMObs
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
init () {
|
|
@@ -16,9 +16,13 @@ class NoopSpan {
|
|
|
16
16
|
setOperationName (name) { return this }
|
|
17
17
|
setBaggageItem (key, value) { return this }
|
|
18
18
|
getBaggageItem (key) {}
|
|
19
|
+
getAllBaggageItems () {}
|
|
20
|
+
removeBaggageItem (key) { return this }
|
|
21
|
+
removeAllBaggageItems () { return this }
|
|
19
22
|
setTag (key, value) { return this }
|
|
20
23
|
addTags (keyValueMap) { return this }
|
|
21
24
|
addLink (link) { return this }
|
|
25
|
+
addSpanPointer (ptrKind, ptrDir, ptrHash) { return this }
|
|
22
26
|
log () { return this }
|
|
23
27
|
logEvent () {}
|
|
24
28
|
finish (finishTime) {}
|
|
@@ -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) {
|
|
@@ -142,7 +143,7 @@ class Span {
|
|
|
142
143
|
context: spanContext._ddContext,
|
|
143
144
|
startTime,
|
|
144
145
|
hostname: _tracer._hostname,
|
|
145
|
-
integrationName: 'otel',
|
|
146
|
+
integrationName: parentTracer?._isOtelLibrary ? 'otel.library' : 'otel',
|
|
146
147
|
tags: {
|
|
147
148
|
[SERVICE_NAME]: _tracer._service,
|
|
148
149
|
[RESOURCE_NAME]: spanName
|
|
@@ -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
|