dd-trace 5.68.0 → 5.70.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 +6 -1
- package/index.d.ts +193 -1
- package/package.json +11 -2
- package/packages/datadog-core/src/storage.js +14 -13
- package/packages/datadog-esbuild/index.js +62 -26
- package/packages/datadog-instrumentations/src/helpers/instrument.js +4 -3
- package/packages/datadog-instrumentations/src/jest.js +86 -84
- package/packages/datadog-instrumentations/src/mocha/utils.js +5 -21
- package/packages/datadog-instrumentations/src/playwright.js +5 -2
- package/packages/datadog-plugin-confluentinc-kafka-javascript/src/index.js +6 -0
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +0 -1
- package/packages/datadog-plugin-mongodb-core/src/index.js +18 -5
- package/packages/dd-trace/src/aiguard/client.js +25 -0
- package/packages/dd-trace/src/aiguard/noop.js +9 -0
- package/packages/dd-trace/src/aiguard/sdk.js +173 -0
- package/packages/dd-trace/src/aiguard/tags.js +11 -0
- package/packages/dd-trace/src/appsec/iast/path-line.js +21 -4
- package/packages/dd-trace/src/appsec/iast/taint-tracking/rewriter.js +6 -3
- package/packages/dd-trace/src/appsec/stack_trace.js +20 -1
- package/packages/dd-trace/src/config-helper.js +8 -1
- package/packages/dd-trace/src/config.js +23 -0
- package/packages/dd-trace/src/config_defaults.js +5 -0
- package/packages/dd-trace/src/datastreams/index.js +23 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/index.js +11 -1
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +8 -6
- package/packages/dd-trace/src/log/index.js +4 -4
- package/packages/dd-trace/src/noop/proxy.js +4 -0
- package/packages/dd-trace/src/opentracing/span.js +1 -1
- package/packages/dd-trace/src/payload-tagging/config/index.js +16 -0
- package/packages/dd-trace/src/payload-tagging/index.js +26 -15
- package/packages/dd-trace/src/payload-tagging/tagging.js +17 -8
- package/packages/dd-trace/src/pkg.js +3 -1
- package/packages/dd-trace/src/plugins/composite.js +3 -0
- package/packages/dd-trace/src/plugins/plugin.js +67 -0
- package/packages/dd-trace/src/plugins/util/git.js +1 -1
- package/packages/dd-trace/src/plugins/util/test.js +19 -30
- package/packages/dd-trace/src/priority_sampler.js +70 -46
- package/packages/dd-trace/src/proxy.js +15 -0
- package/packages/dd-trace/src/rate_limiter.js +26 -1
- package/packages/dd-trace/src/sampling_rule.js +124 -2
- package/packages/dd-trace/src/span_sampler.js +19 -0
- package/packages/dd-trace/src/standalone/product.js +9 -0
- package/packages/dd-trace/src/standalone/tracesource.js +16 -1
- package/packages/dd-trace/src/standalone/tracesource_priority_sampler.js +13 -0
- package/packages/dd-trace/src/startup-log.js +19 -1
- package/packages/dd-trace/src/supported-configurations.json +6 -0
- package/packages/dd-trace/src/util.js +1 -1
- package/version.js +4 -2
package/LICENSE-3rdparty.csv
CHANGED
|
@@ -33,7 +33,11 @@ require,shell-quote,mit,Copyright (c) 2013 James Halliday
|
|
|
33
33
|
require,source-map,BSD-3-Clause,Copyright (c) 2009-2011, Mozilla Foundation and contributors
|
|
34
34
|
require,ttl-set,MIT,Copyright (c) 2024 Thomas Watson
|
|
35
35
|
dev,@babel/helpers,MIT,Copyright (c) 2014-present Sebastian McKenzie and other contributors
|
|
36
|
-
dev,@types/
|
|
36
|
+
dev,@types/chai,MIT,Copyright (c) Microsoft Corp.
|
|
37
|
+
dev,@types/mocha,MIT,Copyright (c) Microsoft Corp.
|
|
38
|
+
dev,@types/node,MIT,Copyright (c) Microsoft Corp.
|
|
39
|
+
dev,@types/sinon,MIT,Copyright (c) Microsoft Corp.
|
|
40
|
+
dev,@types/tap,MIT,Copyright (c) Microsoft Corp.
|
|
37
41
|
dev,@eslint/eslintrc,MIT,Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
|
|
38
42
|
dev,@eslint/js,MIT,Copyright OpenJS Foundation and other contributors, <www.openjsf.org>
|
|
39
43
|
dev,@msgpack/msgpack,ISC,Copyright 2019 The MessagePack Community
|
|
@@ -65,6 +69,7 @@ dev,sinon,BSD-3-Clause,Copyright 2010-2017 Christian Johansen
|
|
|
65
69
|
dev,sinon-chai,WTFPL and BSD-2-Clause,Copyright 2004 Sam Hocevar 2012–2017 Domenic Denicola
|
|
66
70
|
dev,tap,ISC,Copyright 2011-2022 Isaac Z. Schlueter and Contributors
|
|
67
71
|
dev,tiktoken,MIT,Copyright (c) 2022 OpenAI, Shantanu Jain
|
|
72
|
+
dev,typescript,Apache license 2.0,Copyright Microsoft Corp.
|
|
68
73
|
dev,workerpool,Apache license 2.0,Copyright (C) 2014-2024 Jos de Jong wjosdejong@gmail.com
|
|
69
74
|
dev,yaml,ISC,Copyright Eemeli Aro <eemeli@gmail.com>
|
|
70
75
|
dev,yarn-deduplicate,Apache license 2.0,Copyright [yyyy] [name of copyright owner]
|
package/index.d.ts
CHANGED
|
@@ -139,6 +139,11 @@ interface Tracer extends opentracing.Tracer {
|
|
|
139
139
|
*/
|
|
140
140
|
llmobs: tracer.llmobs.LLMObs;
|
|
141
141
|
|
|
142
|
+
/**
|
|
143
|
+
* AI Guard SDK
|
|
144
|
+
*/
|
|
145
|
+
aiguard: tracer.aiguard.AIGuard;
|
|
146
|
+
|
|
142
147
|
/**
|
|
143
148
|
* @experimental
|
|
144
149
|
* Provide same functionality as OpenTelemetry Baggage:
|
|
@@ -593,6 +598,29 @@ declare namespace tracer {
|
|
|
593
598
|
*/
|
|
594
599
|
enabled?: boolean
|
|
595
600
|
}
|
|
601
|
+
},
|
|
602
|
+
|
|
603
|
+
aiguard?: {
|
|
604
|
+
/**
|
|
605
|
+
* Set to `true` to enable the SDK.
|
|
606
|
+
*/
|
|
607
|
+
enabled?: boolean,
|
|
608
|
+
/**
|
|
609
|
+
* URL of the AI Guard REST API.
|
|
610
|
+
*/
|
|
611
|
+
endpoint?: string,
|
|
612
|
+
/**
|
|
613
|
+
* Timeout used in calls to the AI Guard REST API in milliseconds (default 5000)
|
|
614
|
+
*/
|
|
615
|
+
timeout?: number,
|
|
616
|
+
/**
|
|
617
|
+
* Maximum number of conversational messages allowed to be set in the meta-struct
|
|
618
|
+
*/
|
|
619
|
+
maxMessagesLength?: number,
|
|
620
|
+
/**
|
|
621
|
+
* Max size of the content property set in the meta-struct
|
|
622
|
+
*/
|
|
623
|
+
maxContentSize?: number
|
|
596
624
|
}
|
|
597
625
|
};
|
|
598
626
|
|
|
@@ -907,7 +935,7 @@ declare namespace tracer {
|
|
|
907
935
|
scope?: string,
|
|
908
936
|
|
|
909
937
|
/**
|
|
910
|
-
* Custom fields to attach to the user (RBAC, Oauth, etc
|
|
938
|
+
* Custom fields to attach to the user (RBAC, Oauth, etc...).
|
|
911
939
|
*/
|
|
912
940
|
[key: string]: string | undefined
|
|
913
941
|
}
|
|
@@ -1059,6 +1087,170 @@ declare namespace tracer {
|
|
|
1059
1087
|
eventTrackingV2: EventTrackingV2
|
|
1060
1088
|
}
|
|
1061
1089
|
|
|
1090
|
+
export namespace aiguard {
|
|
1091
|
+
|
|
1092
|
+
/**
|
|
1093
|
+
* Represents a tool call made by an AI assistant in an agentic workflow.
|
|
1094
|
+
*/
|
|
1095
|
+
export interface ToolCall {
|
|
1096
|
+
/**
|
|
1097
|
+
* Unique identifier for this specific tool call instance used to correlate the call with its response.
|
|
1098
|
+
*/
|
|
1099
|
+
id: string;
|
|
1100
|
+
/**
|
|
1101
|
+
* Details about the function being invoked.
|
|
1102
|
+
*/
|
|
1103
|
+
function: {
|
|
1104
|
+
/**
|
|
1105
|
+
* The name of the tool/function to be called.
|
|
1106
|
+
*/
|
|
1107
|
+
name: string;
|
|
1108
|
+
/**
|
|
1109
|
+
* String containing the arguments to pass to the tool.
|
|
1110
|
+
*/
|
|
1111
|
+
arguments: string;
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
/**
|
|
1116
|
+
* A standard conversational message exchanged with a Large Language Model (LLM).
|
|
1117
|
+
*/
|
|
1118
|
+
export interface TextMessage {
|
|
1119
|
+
/**
|
|
1120
|
+
* The role of the message sender in the conversation (e.g.: 'system', 'user', 'assistant').
|
|
1121
|
+
*/
|
|
1122
|
+
role: string;
|
|
1123
|
+
/**
|
|
1124
|
+
* The textual content of the message.
|
|
1125
|
+
*/
|
|
1126
|
+
content: string;
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
/**
|
|
1130
|
+
* A message from an AI assistant containing only textual content.
|
|
1131
|
+
*/
|
|
1132
|
+
export interface AssistantTextMessage {
|
|
1133
|
+
/**
|
|
1134
|
+
* The role identifier, always set to 'assistant'
|
|
1135
|
+
*/
|
|
1136
|
+
role: "assistant";
|
|
1137
|
+
/**
|
|
1138
|
+
* The textual response content from the assistant.
|
|
1139
|
+
*/
|
|
1140
|
+
content: string;
|
|
1141
|
+
/**
|
|
1142
|
+
* Explicitly excluded when content is present to maintain type safety.
|
|
1143
|
+
*/
|
|
1144
|
+
tool_calls?: never;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
/**
|
|
1148
|
+
* A message from an AI assistant that initiates one or more tool calls.
|
|
1149
|
+
*/
|
|
1150
|
+
export interface AssistantToolCallMessage {
|
|
1151
|
+
/**
|
|
1152
|
+
* The role identifier, always set to 'assistant'
|
|
1153
|
+
*/
|
|
1154
|
+
role: "assistant";
|
|
1155
|
+
/**
|
|
1156
|
+
* Array of tool calls that the assistant wants to execute.
|
|
1157
|
+
*/
|
|
1158
|
+
tool_calls: ToolCall[];
|
|
1159
|
+
/**
|
|
1160
|
+
* Explicitly excluded when tool calls are present to maintain type safety.
|
|
1161
|
+
*/
|
|
1162
|
+
content?: never;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
/**
|
|
1166
|
+
* A message containing the result of a tool invocation.
|
|
1167
|
+
*/
|
|
1168
|
+
export interface ToolMessage {
|
|
1169
|
+
/**
|
|
1170
|
+
* The role identifier, always set to 'tool' for tool execution results.
|
|
1171
|
+
*/
|
|
1172
|
+
role: "tool";
|
|
1173
|
+
/**
|
|
1174
|
+
* The unique identifier linking this result to the original tool call.
|
|
1175
|
+
* Must correspond to a ToolCall.id from a previous AssistantToolCallMessage.
|
|
1176
|
+
*/
|
|
1177
|
+
tool_call_id: string;
|
|
1178
|
+
/**
|
|
1179
|
+
* The output returned by the tool execution.
|
|
1180
|
+
*/
|
|
1181
|
+
content: string;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1184
|
+
export type Message =
|
|
1185
|
+
| TextMessage
|
|
1186
|
+
| AssistantTextMessage
|
|
1187
|
+
| AssistantToolCallMessage
|
|
1188
|
+
| ToolMessage;
|
|
1189
|
+
|
|
1190
|
+
/**
|
|
1191
|
+
* The result returned by AI Guard after evaluating a conversation.
|
|
1192
|
+
*/
|
|
1193
|
+
export interface Evaluation {
|
|
1194
|
+
/**
|
|
1195
|
+
* The security action determined by AI Guard:
|
|
1196
|
+
* - 'ALLOW': The conversation is safe to proceed
|
|
1197
|
+
* - 'DENY': The current conversation exchange should be blocked
|
|
1198
|
+
* - 'ABORT': The full workflow should be terminated immediately
|
|
1199
|
+
*/
|
|
1200
|
+
action: 'ALLOW' | 'DENY' | 'ABORT';
|
|
1201
|
+
/**
|
|
1202
|
+
* Human-readable explanation for why this action was chosen.
|
|
1203
|
+
*/
|
|
1204
|
+
reason: string;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
/**
|
|
1208
|
+
* Error thrown when AI Guard evaluation determines that a conversation should be blocked
|
|
1209
|
+
* and the client is configured to enforce blocking mode.
|
|
1210
|
+
*/
|
|
1211
|
+
export interface AIGuardAbortError extends Error {
|
|
1212
|
+
/**
|
|
1213
|
+
* Human-readable explanation from AI Guard describing why the conversation was blocked.
|
|
1214
|
+
*/
|
|
1215
|
+
reason: string;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
/**
|
|
1219
|
+
* Error thrown when the AI Guard SDK encounters communication failures or API errors while attempting to
|
|
1220
|
+
* evaluate conversations.
|
|
1221
|
+
*/
|
|
1222
|
+
export interface AIGuardClientError extends Error {
|
|
1223
|
+
/**
|
|
1224
|
+
* Detailed error information returned by the AI Guard API, formatted according to the JSON:API error
|
|
1225
|
+
* specification.
|
|
1226
|
+
*/
|
|
1227
|
+
errors?: unknown[];
|
|
1228
|
+
/**
|
|
1229
|
+
* The underlying error that caused the communication failure, such as network timeouts, connection refused,
|
|
1230
|
+
* or JSON parsing errors.
|
|
1231
|
+
*/
|
|
1232
|
+
cause?: Error;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
/**
|
|
1236
|
+
* AI Guard security client for evaluating AI conversations.
|
|
1237
|
+
*/
|
|
1238
|
+
export interface AIGuard {
|
|
1239
|
+
/**
|
|
1240
|
+
* Evaluates a conversation thread.
|
|
1241
|
+
*
|
|
1242
|
+
* @param messages - Array of conversation messages
|
|
1243
|
+
* @param opts - Optional configuration object:
|
|
1244
|
+
* - `block`: When true, throws an exception if evaluation result is not 'ALLOW'
|
|
1245
|
+
* and the AI Guard service has blocking mode enabled (default: false).
|
|
1246
|
+
* @returns Promise resolving to an Evaluation with the security decision and reasoning.
|
|
1247
|
+
* The promise rejects with AIGuardAbortError when `opts.block` is true and the evaluation result would block the request.
|
|
1248
|
+
* The promise rejects with AIGuardClientError when communication with the AI Guard service fails.
|
|
1249
|
+
*/
|
|
1250
|
+
evaluate (messages: Message[], opts?: { block?: boolean }): Promise<Evaluation>;
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
|
|
1062
1254
|
/** @hidden */
|
|
1063
1255
|
type anyObject = {
|
|
1064
1256
|
[key: string]: any;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dd-trace",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.70.0",
|
|
4
4
|
"description": "Datadog APM tracing client for JavaScript",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"typings": "index.d.ts",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"bench": "node benchmark/index.js",
|
|
11
11
|
"bench:e2e:test-optimization": "node benchmark/e2e-test-optimization/benchmark-run.js",
|
|
12
12
|
"dependencies:dedupe": "yarn-deduplicate yarn.lock",
|
|
13
|
+
"type:check": "tsc --noEmit -p tsconfig.json",
|
|
13
14
|
"type:doc": "cd docs && yarn && yarn build",
|
|
14
15
|
"type:test": "cd docs && yarn && yarn test",
|
|
15
16
|
"lint": "node scripts/check_licenses.js && eslint . --concurrency=auto --max-warnings 0",
|
|
@@ -18,6 +19,8 @@
|
|
|
18
19
|
"release:proposal": "node scripts/release/proposal",
|
|
19
20
|
"services": "node ./scripts/install_plugin_modules && node packages/dd-trace/test/setup/services",
|
|
20
21
|
"test": "SERVICES=* yarn services && mocha --expose-gc 'packages/dd-trace/test/setup/node.js' 'packages/*/test/**/*.spec.js'",
|
|
22
|
+
"test:aiguard": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/dd-trace/test/aiguard/**/*.spec.js\"",
|
|
23
|
+
"test:aiguard:ci": "nyc --no-clean --include \"packages/dd-trace/src/aiguard/**/*.js\" -- npm run test:aiguard",
|
|
21
24
|
"test:appsec": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" --exclude \"packages/dd-trace/test/appsec/**/*.plugin.spec.js\" \"packages/dd-trace/test/appsec/**/*.spec.js\"",
|
|
22
25
|
"test:appsec:ci": "nyc --no-clean --include \"packages/dd-trace/src/appsec/**/*.js\" --exclude \"packages/dd-trace/test/appsec/**/*.plugin.spec.js\" -- npm run test:appsec",
|
|
23
26
|
"test:appsec:plugins": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/dd-trace/test/appsec/**/*.@($(echo $PLUGINS)).plugin.spec.js\"",
|
|
@@ -47,6 +50,7 @@
|
|
|
47
50
|
"test:profiler": "tap \"packages/dd-trace/test/profiling/**/*.spec.js\"",
|
|
48
51
|
"test:profiler:ci": "npm run test:profiler -- --coverage --nyc-arg=--include=\"packages/dd-trace/src/profiling/**/*.js\"",
|
|
49
52
|
"test:integration": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/*.spec.js\"",
|
|
53
|
+
"test:integration:aiguard": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/aiguard/*.spec.js\"",
|
|
50
54
|
"test:integration:appsec": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/appsec/*.spec.js\"",
|
|
51
55
|
"test:integration:cucumber": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/cucumber/*.spec.js\"",
|
|
52
56
|
"test:integration:cypress": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/cypress/*.spec.js\"",
|
|
@@ -57,7 +61,7 @@
|
|
|
57
61
|
"test:integration:playwright": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/playwright/*.spec.js\"",
|
|
58
62
|
"test:integration:selenium": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/selenium/*.spec.js\"",
|
|
59
63
|
"test:integration:vitest": "mocha --timeout 60000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/vitest/*.spec.js\"",
|
|
60
|
-
"test:integration:testopt": "mocha --timeout
|
|
64
|
+
"test:integration:testopt": "mocha --timeout 90000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/ci-visibility/*.spec.js\"",
|
|
61
65
|
"test:integration:profiler": "mocha --timeout 180000 -r \"packages/dd-trace/test/setup/core.js\" \"integration-tests/profiler/*.spec.js\"",
|
|
62
66
|
"test:integration:plugins": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/datadog-plugin-@($(echo $PLUGINS))/test/integration-test/**/*.spec.js\"",
|
|
63
67
|
"test:unit:plugins": "mocha -r \"packages/dd-trace/test/setup/mocha.js\" \"packages/datadog-instrumentations/test/@($(echo $PLUGINS)).spec.js\" \"packages/datadog-plugin-@($(echo $PLUGINS))/test/**/*.spec.js\" --exclude \"packages/datadog-plugin-@($(echo $PLUGINS))/test/integration-test/**/*.spec.js\"",
|
|
@@ -153,7 +157,11 @@
|
|
|
153
157
|
"@eslint/js": "^9.29.0",
|
|
154
158
|
"@msgpack/msgpack": "^3.1.2",
|
|
155
159
|
"@stylistic/eslint-plugin": "^5.0.0",
|
|
160
|
+
"@types/chai": "^4.3.16",
|
|
161
|
+
"@types/mocha": "^10.0.10",
|
|
156
162
|
"@types/node": "^18.19.106",
|
|
163
|
+
"@types/sinon": "^17.0.4",
|
|
164
|
+
"@types/tap": "^15.0.12",
|
|
157
165
|
"axios": "^1.12.2",
|
|
158
166
|
"benchmark": "^2.1.4",
|
|
159
167
|
"body-parser": "^2.2.0",
|
|
@@ -181,6 +189,7 @@
|
|
|
181
189
|
"sinon-chai": "^3.7.0",
|
|
182
190
|
"tap": "^16.3.10",
|
|
183
191
|
"tiktoken": "^1.0.21",
|
|
192
|
+
"typescript": "^5.9.2",
|
|
184
193
|
"workerpool": "^9.2.0",
|
|
185
194
|
"yaml": "^2.8.0",
|
|
186
195
|
"yarn-deduplicate": "^6.0.2"
|
|
@@ -10,12 +10,13 @@ const { AsyncLocalStorage } = require('async_hooks')
|
|
|
10
10
|
* a "handle" object, which is used as a key in a WeakMap, where the values
|
|
11
11
|
* are the real store objects.
|
|
12
12
|
*
|
|
13
|
-
* @
|
|
13
|
+
* @typedef {Record<string, unknown>} Store
|
|
14
14
|
*/
|
|
15
15
|
class DatadogStorage extends AsyncLocalStorage {
|
|
16
16
|
/**
|
|
17
17
|
*
|
|
18
|
-
* @param store {
|
|
18
|
+
* @param store {Store}
|
|
19
|
+
* @override
|
|
19
20
|
*/
|
|
20
21
|
enterWith (store) {
|
|
21
22
|
const handle = {}
|
|
@@ -34,7 +35,7 @@ class DatadogStorage extends AsyncLocalStorage {
|
|
|
34
35
|
*
|
|
35
36
|
* TODO: Refactor the Scope class to use a span-only store and remove this.
|
|
36
37
|
*
|
|
37
|
-
* @returns {
|
|
38
|
+
* @returns {Store}
|
|
38
39
|
*/
|
|
39
40
|
getHandle () {
|
|
40
41
|
return super.getStore()
|
|
@@ -46,9 +47,9 @@ class DatadogStorage extends AsyncLocalStorage {
|
|
|
46
47
|
* retrieved through `getHandle()` can also be passed in to be used as the
|
|
47
48
|
* key. This is useful if you've stashed a handle somewhere and want to
|
|
48
49
|
* retrieve the store with it.
|
|
49
|
-
*
|
|
50
|
-
* @
|
|
51
|
-
* @
|
|
50
|
+
* @param {{}} [handle]
|
|
51
|
+
* @returns {Store | undefined}
|
|
52
|
+
* @override
|
|
52
53
|
*/
|
|
53
54
|
getStore (handle) {
|
|
54
55
|
if (!handle) {
|
|
@@ -66,11 +67,12 @@ class DatadogStorage extends AsyncLocalStorage {
|
|
|
66
67
|
* when dealing with the parent store, so that we don't have to access the
|
|
67
68
|
* WeakMap.
|
|
68
69
|
* @template R
|
|
69
|
-
* @template TArgs
|
|
70
|
-
* @param
|
|
71
|
-
* @param
|
|
72
|
-
* @param
|
|
73
|
-
* @returns {
|
|
70
|
+
* @template TArgs = unknown[]
|
|
71
|
+
* @param {Store} store
|
|
72
|
+
* @param {() => R} fn
|
|
73
|
+
* @param {...TArgs} args
|
|
74
|
+
* @returns {R}
|
|
75
|
+
* @override
|
|
74
76
|
*/
|
|
75
77
|
run (store, fn, ...args) {
|
|
76
78
|
const prior = super.getStore()
|
|
@@ -85,8 +87,7 @@ class DatadogStorage extends AsyncLocalStorage {
|
|
|
85
87
|
|
|
86
88
|
/**
|
|
87
89
|
* This is the map from handles to real stores, used in the class above.
|
|
88
|
-
* @
|
|
89
|
-
* @type {WeakMap<WeakKey, T>}
|
|
90
|
+
* @type {WeakMap<WeakKey, Store>}
|
|
90
91
|
*/
|
|
91
92
|
const stores = new WeakMap()
|
|
92
93
|
|
|
@@ -8,6 +8,8 @@ const extractPackageAndModulePath = require(
|
|
|
8
8
|
'../datadog-instrumentations/src/helpers/extract-package-and-module-path.js'
|
|
9
9
|
)
|
|
10
10
|
|
|
11
|
+
let rewriter
|
|
12
|
+
|
|
11
13
|
for (const hook of Object.values(hooks)) {
|
|
12
14
|
if (typeof hook === 'object') {
|
|
13
15
|
hook.fn()
|
|
@@ -43,6 +45,7 @@ for (const builtin of RAW_BUILTINS) {
|
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
const DEBUG = !!process.env.DD_TRACE_DEBUG
|
|
48
|
+
const DD_IAST_ENABLED = process.env.DD_IAST_ENABLED?.toLowerCase() === 'true' || process.env.DD_IAST_ENABLED === '1'
|
|
46
49
|
|
|
47
50
|
// We don't want to handle any built-in packages
|
|
48
51
|
// Those packages will still be handled via RITM
|
|
@@ -96,10 +99,23 @@ function getGitMetadata () {
|
|
|
96
99
|
}
|
|
97
100
|
|
|
98
101
|
module.exports.setup = function (build) {
|
|
102
|
+
if (DD_IAST_ENABLED) {
|
|
103
|
+
const iastRewriter = require('../dd-trace/src/appsec/iast/taint-tracking/rewriter')
|
|
104
|
+
rewriter = iastRewriter.getRewriter()
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const isSourceMapEnabled = !!build.initialOptions.sourcemap ||
|
|
108
|
+
['internal', 'both'].includes(build.initialOptions.sourcemap)
|
|
99
109
|
const externalModules = new Set(build.initialOptions.external || [])
|
|
110
|
+
build.initialOptions.banner ??= {}
|
|
111
|
+
build.initialOptions.banner.js ??= ''
|
|
112
|
+
if (DD_IAST_ENABLED) {
|
|
113
|
+
build.initialOptions.banner.js =
|
|
114
|
+
`globalThis.__DD_ESBUILD_IAST_${isSourceMapEnabled ? 'WITH_SM' : 'WITH_NO_SM'} = true;
|
|
115
|
+
${isSourceMapEnabled ? `globalThis.__DD_ESBUILD_BASEPATH = '${require('../dd-trace/src/util').ddBasePath}';` : ''}
|
|
116
|
+
${build.initialOptions.banner.js}`
|
|
117
|
+
}
|
|
100
118
|
if (isESMBuild(build)) {
|
|
101
|
-
build.initialOptions.banner ??= {}
|
|
102
|
-
build.initialOptions.banner.js ??= ''
|
|
103
119
|
if (!build.initialOptions.banner.js.includes('import { createRequire as $dd_createRequire } from \'module\'')) {
|
|
104
120
|
build.initialOptions.banner.js = `import { createRequire as $dd_createRequire } from 'module';
|
|
105
121
|
import { fileURLToPath as $dd_fileURLToPath } from 'url';
|
|
@@ -140,13 +156,6 @@ ${build.initialOptions.banner.js}`
|
|
|
140
156
|
return
|
|
141
157
|
}
|
|
142
158
|
|
|
143
|
-
// TODO: Should this also check for namespace === 'file'?
|
|
144
|
-
if (args.path.startsWith('.') && !args.importer.includes('node_modules/')) {
|
|
145
|
-
// This is local application code, not an instrumented package
|
|
146
|
-
if (DEBUG) console.log(`LOCAL: ${args.path}`)
|
|
147
|
-
return
|
|
148
|
-
}
|
|
149
|
-
|
|
150
159
|
// TODO: Should this also check for namespace === 'file'?
|
|
151
160
|
if (!modulesOfInterest.has(args.path) &&
|
|
152
161
|
args.path.startsWith('@') &&
|
|
@@ -166,6 +175,21 @@ ${build.initialOptions.banner.js}`
|
|
|
166
175
|
}
|
|
167
176
|
return
|
|
168
177
|
}
|
|
178
|
+
|
|
179
|
+
if (args.path.startsWith('.') && !args.importer.includes('node_modules/')) {
|
|
180
|
+
// It is local application code, not an instrumented package
|
|
181
|
+
if (DEBUG) console.log(`APP: ${args.path}`)
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
path: fullPathToModule,
|
|
185
|
+
pluginData: {
|
|
186
|
+
path: args.path,
|
|
187
|
+
full: fullPathToModule,
|
|
188
|
+
applicationFile: true
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
169
193
|
const extracted = extractPackageAndModulePath(fullPathToModule)
|
|
170
194
|
|
|
171
195
|
const internal = builtins.has(args.path)
|
|
@@ -215,22 +239,19 @@ ${build.initialOptions.banner.js}`
|
|
|
215
239
|
})
|
|
216
240
|
|
|
217
241
|
build.onLoad({ filter: /.*/ }, args => {
|
|
218
|
-
if (
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const data = args.pluginData
|
|
242
|
+
if (args.pluginData?.pkgOfInterest) {
|
|
243
|
+
const data = args.pluginData
|
|
223
244
|
|
|
224
|
-
|
|
245
|
+
if (DEBUG) console.log(`LOAD: ${data.pkg}@${data.version}, pkg "${data.path}"`)
|
|
225
246
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
247
|
+
const pkgPath = data.raw !== data.pkg
|
|
248
|
+
? `${data.pkg}/${data.path}`
|
|
249
|
+
: data.pkg
|
|
229
250
|
|
|
230
|
-
|
|
231
|
-
|
|
251
|
+
// Read the content of the module file of interest
|
|
252
|
+
const fileCode = fs.readFileSync(args.path, 'utf8')
|
|
232
253
|
|
|
233
|
-
|
|
254
|
+
const contents = `
|
|
234
255
|
(function() {
|
|
235
256
|
${fileCode}
|
|
236
257
|
})(...arguments);
|
|
@@ -248,12 +269,27 @@ ${build.initialOptions.banner.js}`
|
|
|
248
269
|
module.exports = payload.module;
|
|
249
270
|
}
|
|
250
271
|
`
|
|
272
|
+
// https://esbuild.github.io/plugins/#on-load-results
|
|
273
|
+
return {
|
|
274
|
+
contents,
|
|
275
|
+
loader: 'js',
|
|
276
|
+
resolveDir: path.dirname(args.path)
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (DD_IAST_ENABLED && args.pluginData?.applicationFile) {
|
|
281
|
+
const ext = path.extname(args.path).toLowerCase()
|
|
282
|
+
const isJs = /^\.(js|mjs|cjs)$/.test(ext)
|
|
283
|
+
if (!isJs) return
|
|
251
284
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
285
|
+
if (DEBUG) console.log(`REWRITE: ${args.path}`)
|
|
286
|
+
const fileCode = fs.readFileSync(args.path, 'utf8')
|
|
287
|
+
const rewritten = rewriter.rewrite(fileCode, args.path, ['iast'])
|
|
288
|
+
return {
|
|
289
|
+
contents: rewritten.content,
|
|
290
|
+
loader: 'js',
|
|
291
|
+
resolveDir: path.dirname(args.path)
|
|
292
|
+
}
|
|
257
293
|
}
|
|
258
294
|
})
|
|
259
295
|
}
|
|
@@ -23,10 +23,11 @@ exports.tracingChannel = function (name) {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* @param {
|
|
26
|
+
* @param {object} args
|
|
27
|
+
* @param {string|string[]} args.name module name
|
|
27
28
|
* @param {string[]} args.versions array of semver range strings
|
|
28
|
-
* @param {string} args.file path to file within package to instrument
|
|
29
|
-
* @param {string} args.filePattern pattern to match files within package to instrument
|
|
29
|
+
* @param {string} [args.file='index.js'] path to file within package to instrument
|
|
30
|
+
* @param {string} [args.filePattern] pattern to match files within package to instrument
|
|
30
31
|
* @param Function hook
|
|
31
32
|
*/
|
|
32
33
|
exports.addHook = function addHook ({ name, versions, file, filePattern, patchDefault }, hook) {
|