dd-trace 5.104.0 → 5.105.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 +90 -102
- package/index.d.ts +82 -3
- package/package.json +15 -15
- package/packages/datadog-core/src/storage.js +1 -1
- package/packages/datadog-instrumentations/src/aerospike.js +1 -1
- package/packages/datadog-instrumentations/src/ai.js +8 -7
- package/packages/datadog-instrumentations/src/aws-sdk.js +13 -0
- package/packages/datadog-instrumentations/src/azure-cosmos.js +7 -0
- package/packages/datadog-instrumentations/src/azure-functions.js +3 -0
- package/packages/datadog-instrumentations/src/cucumber.js +78 -5
- package/packages/datadog-instrumentations/src/dns.js +54 -18
- package/packages/datadog-instrumentations/src/fastify.js +142 -82
- package/packages/datadog-instrumentations/src/graphql.js +188 -62
- package/packages/datadog-instrumentations/src/helpers/ai-messages.js +322 -14
- package/packages/datadog-instrumentations/src/helpers/hooks.js +4 -0
- package/packages/datadog-instrumentations/src/helpers/instrument.js +2 -1
- package/packages/datadog-instrumentations/src/helpers/openai-ai-guard.js +269 -0
- package/packages/datadog-instrumentations/src/helpers/promise-instrumentor.js +42 -0
- package/packages/datadog-instrumentations/src/helpers/register.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/rewriter/index.js +2 -3
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/azure-cosmos.js +50 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/langgraph.js +4 -2
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/playwright.js +85 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +37 -236
- package/packages/datadog-instrumentations/src/hono.js +54 -3
- package/packages/datadog-instrumentations/src/http/server.js +9 -4
- package/packages/datadog-instrumentations/src/jest/coverage-backfill.js +163 -0
- package/packages/datadog-instrumentations/src/jest.js +360 -150
- package/packages/datadog-instrumentations/src/kafkajs.js +120 -16
- package/packages/datadog-instrumentations/src/mocha/main.js +128 -17
- package/packages/datadog-instrumentations/src/nats.js +182 -0
- package/packages/datadog-instrumentations/src/nyc.js +38 -1
- package/packages/datadog-instrumentations/src/openai.js +33 -18
- package/packages/datadog-instrumentations/src/oracledb.js +6 -1
- package/packages/datadog-instrumentations/src/pino.js +17 -5
- package/packages/datadog-instrumentations/src/playwright.js +515 -292
- package/packages/datadog-instrumentations/src/router.js +76 -32
- package/packages/datadog-instrumentations/src/stripe.js +1 -1
- package/packages/datadog-plugin-avsc/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-azure-cosmos/src/index.js +144 -0
- package/packages/datadog-plugin-azure-event-hubs/src/producer.js +1 -1
- package/packages/datadog-plugin-azure-functions/src/index.js +5 -2
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +1 -1
- package/packages/datadog-plugin-bunyan/src/index.js +28 -0
- package/packages/datadog-plugin-cucumber/src/index.js +17 -3
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +199 -28
- package/packages/datadog-plugin-cypress/src/support.js +69 -1
- package/packages/datadog-plugin-dns/src/lookup.js +8 -6
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +1 -1
- package/packages/datadog-plugin-graphql/src/execute.js +2 -0
- package/packages/datadog-plugin-graphql/src/resolve.js +64 -67
- package/packages/datadog-plugin-http/src/server.js +40 -15
- package/packages/datadog-plugin-jest/src/index.js +11 -3
- package/packages/datadog-plugin-jest/src/util.js +15 -8
- package/packages/datadog-plugin-kafkajs/src/batch-consumer.js +1 -1
- package/packages/datadog-plugin-kafkajs/src/producer.js +3 -0
- package/packages/datadog-plugin-langgraph/src/stream.js +1 -1
- package/packages/datadog-plugin-mocha/src/index.js +19 -4
- package/packages/datadog-plugin-mongodb-core/src/index.js +281 -40
- package/packages/datadog-plugin-nats/src/consumer.js +43 -0
- package/packages/datadog-plugin-nats/src/index.js +20 -0
- package/packages/datadog-plugin-nats/src/producer.js +62 -0
- package/packages/datadog-plugin-nats/src/util.js +33 -0
- package/packages/datadog-plugin-next/src/index.js +5 -3
- package/packages/datadog-plugin-openai/src/tracing.js +15 -2
- package/packages/datadog-plugin-oracledb/src/index.js +13 -2
- package/packages/datadog-plugin-pino/src/index.js +42 -0
- package/packages/datadog-plugin-playwright/src/index.js +4 -4
- package/packages/datadog-plugin-protobufjs/src/schema_iterator.js +1 -1
- package/packages/datadog-plugin-rhea/src/producer.js +1 -1
- package/packages/datadog-plugin-router/src/index.js +33 -44
- package/packages/datadog-plugin-selenium/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +5 -13
- package/packages/datadog-plugin-winston/src/index.js +30 -0
- package/packages/datadog-shimmer/src/shimmer.js +33 -40
- package/packages/dd-trace/src/aiguard/index.js +1 -1
- package/packages/dd-trace/src/aiguard/sdk.js +1 -1
- package/packages/dd-trace/src/appsec/api_security_sampler.js +1 -1
- package/packages/dd-trace/src/appsec/index.js +1 -1
- package/packages/dd-trace/src/appsec/reporter.js +5 -6
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +1 -1
- package/packages/dd-trace/src/appsec/sdk/utils.js +1 -1
- package/packages/dd-trace/src/appsec/user_tracking.js +5 -4
- package/packages/dd-trace/src/baggage.js +7 -1
- package/packages/dd-trace/src/ci-visibility/exporters/ci-visibility-exporter.js +0 -1
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +25 -13
- package/packages/dd-trace/src/ci-visibility/test-optimization-cache.js +70 -6
- package/packages/dd-trace/src/config/generated-config-types.d.ts +6 -2
- package/packages/dd-trace/src/config/supported-configurations.json +27 -8
- package/packages/dd-trace/src/datastreams/writer.js +2 -4
- package/packages/dd-trace/src/debugger/devtools_client/condition.js +5 -8
- package/packages/dd-trace/src/encode/0.4.js +124 -108
- package/packages/dd-trace/src/encode/0.5.js +114 -26
- package/packages/dd-trace/src/encode/agentless-ci-visibility.js +31 -23
- package/packages/dd-trace/src/encode/agentless-json.js +4 -2
- package/packages/dd-trace/src/encode/coverage-ci-visibility.js +32 -13
- package/packages/dd-trace/src/encode/span-stats.js +16 -16
- package/packages/dd-trace/src/encode/tags-processors.js +16 -0
- package/packages/dd-trace/src/llmobs/plugins/ai/util.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/genai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/index.js +9 -7
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -1
- package/packages/dd-trace/src/llmobs/plugins/openai/index.js +1 -1
- package/packages/dd-trace/src/llmobs/sdk.js +0 -16
- package/packages/dd-trace/src/llmobs/span_processor.js +3 -3
- package/packages/dd-trace/src/llmobs/tagger.js +9 -1
- package/packages/dd-trace/src/llmobs/telemetry.js +1 -1
- package/packages/dd-trace/src/llmobs/util.js +66 -3
- package/packages/dd-trace/src/log/index.js +1 -1
- package/packages/dd-trace/src/msgpack/chunk.js +394 -10
- package/packages/dd-trace/src/msgpack/index.js +96 -2
- package/packages/dd-trace/src/openfeature/encoding.js +70 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +20 -0
- package/packages/dd-trace/src/openfeature/span-enrichment-hook.js +143 -0
- package/packages/dd-trace/src/openfeature/span-enrichment.js +149 -0
- package/packages/dd-trace/src/opentelemetry/span-helpers.js +4 -3
- package/packages/dd-trace/src/opentelemetry/span.js +1 -1
- package/packages/dd-trace/src/opentracing/propagation/log.js +18 -7
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +62 -67
- package/packages/dd-trace/src/opentracing/span.js +59 -19
- package/packages/dd-trace/src/opentracing/span_context.js +49 -0
- package/packages/dd-trace/src/plugins/ci_plugin.js +20 -20
- package/packages/dd-trace/src/plugins/database.js +7 -6
- package/packages/dd-trace/src/plugins/index.js +4 -0
- package/packages/dd-trace/src/plugins/log_injection.js +56 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +3 -48
- package/packages/dd-trace/src/plugins/outbound.js +1 -1
- package/packages/dd-trace/src/plugins/plugin.js +15 -17
- package/packages/dd-trace/src/plugins/tracing.js +43 -5
- package/packages/dd-trace/src/plugins/util/test.js +236 -13
- package/packages/dd-trace/src/plugins/util/web.js +79 -65
- package/packages/dd-trace/src/priority_sampler.js +2 -2
- package/packages/dd-trace/src/profiling/profiler.js +2 -2
- package/packages/dd-trace/src/profiling/profilers/wall.js +10 -4
- package/packages/dd-trace/src/sampling_rule.js +7 -7
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +10 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/messaging.js +8 -0
- package/packages/dd-trace/src/service-naming/source-resolver.js +46 -0
- package/packages/dd-trace/src/span_format.js +190 -58
- package/packages/dd-trace/src/spanleak.js +1 -1
- package/packages/dd-trace/src/standalone/index.js +3 -3
- package/packages/dd-trace/src/tagger.js +0 -2
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +70 -39
- package/vendor/dist/@datadog/sketches-js/LICENSE +10 -36
- package/vendor/dist/@datadog/sketches-js/index.js +1 -1
- package/vendor/dist/protobufjs/index.js +1 -1
- package/vendor/dist/protobufjs/minimal/index.js +1 -1
- package/packages/dd-trace/src/msgpack/encoder.js +0 -308
- package/packages/dd-trace/src/plugins/structured_log_plugin.js +0 -9
|
@@ -229,11 +229,11 @@ const BASE_LIKE_BRANCH_FILTER = /^(main|master|preprod|prod|dev|development|trun
|
|
|
229
229
|
|
|
230
230
|
/**
|
|
231
231
|
* Returns request error tags from a test session span for propagation to child events.
|
|
232
|
-
* @param {{ context: () => {
|
|
232
|
+
* @param {{ context: () => { getTag?: (key: string) => string } } | undefined} sessionSpan
|
|
233
233
|
* @returns {Record<string, string>}
|
|
234
234
|
*/
|
|
235
235
|
function getSessionRequestErrorTags (sessionSpan) {
|
|
236
|
-
const tags = sessionSpan?.context()
|
|
236
|
+
const tags = sessionSpan?.context()?.getTags?.()
|
|
237
237
|
const sessionRequestErrorTags = {}
|
|
238
238
|
if (!tags || typeof tags !== 'object') return {}
|
|
239
239
|
if (tags[DD_CI_LIBRARY_CONFIGURATION_ERROR_SETTINGS] === 'true') {
|
|
@@ -253,11 +253,11 @@ function getSessionRequestErrorTags (sessionSpan) {
|
|
|
253
253
|
|
|
254
254
|
/**
|
|
255
255
|
* Returns ITR skipping-enabled tags from a test session span for propagation to child events.
|
|
256
|
-
* @param {{ context: () => {
|
|
256
|
+
* @param {{ context: () => { getTags?: () => Record<string, string> } } | undefined} sessionSpan
|
|
257
257
|
* @returns {Record<string, string>}
|
|
258
258
|
*/
|
|
259
259
|
function getSessionItrSkippingEnabledTags (sessionSpan) {
|
|
260
|
-
const tags = sessionSpan?.context()
|
|
260
|
+
const tags = sessionSpan?.context()?.getTags?.()
|
|
261
261
|
if (!tags || typeof tags !== 'object') return {}
|
|
262
262
|
if (tags[TEST_ITR_SKIPPING_ENABLED] !== undefined) {
|
|
263
263
|
return {
|
|
@@ -418,6 +418,12 @@ module.exports = {
|
|
|
418
418
|
ITR_CORRELATION_ID,
|
|
419
419
|
addIntelligentTestRunnerSpanTags,
|
|
420
420
|
getCoveredFilenamesFromCoverage,
|
|
421
|
+
getCoveredFilesFromCoverage,
|
|
422
|
+
getExecutableFilesFromCoverage,
|
|
423
|
+
getRelativeCoverageFiles,
|
|
424
|
+
getLineCoverageBitmap,
|
|
425
|
+
applySkippedCoverageToCoverage,
|
|
426
|
+
getTestCoverageLinesPercentage,
|
|
421
427
|
resetCoverage,
|
|
422
428
|
mergeCoverage,
|
|
423
429
|
fromCoverageMapToCoverage,
|
|
@@ -952,7 +958,6 @@ function getTestLevelCommonTags (command, testFrameworkVersion, testFramework) {
|
|
|
952
958
|
return {
|
|
953
959
|
[TEST_FRAMEWORK_VERSION]: testFrameworkVersion,
|
|
954
960
|
[LIBRARY_VERSION]: ddTraceVersion,
|
|
955
|
-
[TEST_COMMAND]: command,
|
|
956
961
|
[TEST_TYPE]: getTestTypeFromFramework(testFramework),
|
|
957
962
|
}
|
|
958
963
|
}
|
|
@@ -1030,15 +1035,233 @@ function addIntelligentTestRunnerSpanTags (
|
|
|
1030
1035
|
}
|
|
1031
1036
|
|
|
1032
1037
|
function getCoveredFilenamesFromCoverage (coverage) {
|
|
1033
|
-
|
|
1038
|
+
return getCoveredFilesFromCoverage(coverage).map(({ filename }) => filename)
|
|
1039
|
+
}
|
|
1034
1040
|
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1041
|
+
function getCoverageMap (coverage) {
|
|
1042
|
+
if (coverage?.files && coverage?.fileCoverageFor) {
|
|
1043
|
+
return coverage
|
|
1044
|
+
}
|
|
1045
|
+
return istanbul.createCoverageMap(coverage)
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
function getCoveredFilesFromCoverage (coverage) {
|
|
1049
|
+
const coverageMap = getCoverageMap(coverage)
|
|
1050
|
+
const coverageFiles = []
|
|
1051
|
+
|
|
1052
|
+
for (const filename of coverageMap.files()) {
|
|
1053
|
+
const fileCoverage = coverageMap.fileCoverageFor(filename)
|
|
1054
|
+
const bitmap = getLineCoverageBitmap(fileCoverage.getLineCoverage(), true)
|
|
1055
|
+
if (bitmap) {
|
|
1056
|
+
coverageFiles.push({ filename, bitmap })
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
return coverageFiles
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
function getExecutableFilesFromCoverage (coverage) {
|
|
1064
|
+
const coverageMap = getCoverageMap(coverage)
|
|
1065
|
+
const coverageFiles = []
|
|
1066
|
+
|
|
1067
|
+
for (const filename of coverageMap.files()) {
|
|
1068
|
+
const fileCoverage = coverageMap.fileCoverageFor(filename)
|
|
1069
|
+
const bitmap = getLineCoverageBitmap(fileCoverage.getLineCoverage())
|
|
1070
|
+
if (bitmap) {
|
|
1071
|
+
coverageFiles.push({ filename, bitmap })
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
return coverageFiles
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
function getRelativeCoverageFiles (coverageFiles, rootDir) {
|
|
1079
|
+
return coverageFiles.map(({ filename, bitmap }) => ({
|
|
1080
|
+
filename: getTestSuitePath(filename, rootDir),
|
|
1081
|
+
bitmap,
|
|
1082
|
+
}))
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
function getLineCoverageBitmap (lineCoverage, onlyCoveredLines = false) {
|
|
1086
|
+
let maxLine = 0
|
|
1087
|
+
const lines = []
|
|
1088
|
+
|
|
1089
|
+
for (const [line, hits] of Object.entries(lineCoverage)) {
|
|
1090
|
+
if (onlyCoveredLines && !hits) continue
|
|
1091
|
+
|
|
1092
|
+
const lineNumber = Number(line)
|
|
1093
|
+
if (!Number.isSafeInteger(lineNumber) || lineNumber <= 0) continue
|
|
1094
|
+
|
|
1095
|
+
lines.push(lineNumber)
|
|
1096
|
+
if (lineNumber > maxLine) {
|
|
1097
|
+
maxLine = lineNumber
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
if (maxLine === 0) return
|
|
1102
|
+
|
|
1103
|
+
const bitmap = Buffer.alloc(Math.ceil((maxLine + 1) / 8))
|
|
1104
|
+
for (const lineNumber of lines) {
|
|
1105
|
+
bitmap[lineNumber >> 3] |= 1 << (lineNumber % 8)
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
return bitmap
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
function mergeCoverageBitmaps (targetBitmap, bitmap) {
|
|
1112
|
+
if (!targetBitmap) {
|
|
1113
|
+
return Buffer.from(bitmap)
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
if (targetBitmap.length < bitmap.length) {
|
|
1117
|
+
const biggerBitmap = Buffer.alloc(bitmap.length)
|
|
1118
|
+
targetBitmap.copy(biggerBitmap)
|
|
1119
|
+
targetBitmap = biggerBitmap
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
for (let i = 0; i < bitmap.length; i++) {
|
|
1123
|
+
targetBitmap[i] |= bitmap[i]
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
return targetBitmap
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
function countBitmapBits (bitmap) {
|
|
1130
|
+
let count = 0
|
|
1131
|
+
|
|
1132
|
+
for (const byte of bitmap) {
|
|
1133
|
+
let value = byte
|
|
1134
|
+
while (value) {
|
|
1135
|
+
value &= value - 1
|
|
1136
|
+
count++
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
return count
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
function countCoveredExecutableBits (coveredBitmap, executableBitmap) {
|
|
1144
|
+
if (!coveredBitmap) return 0
|
|
1145
|
+
|
|
1146
|
+
let count = 0
|
|
1147
|
+
const length = Math.min(coveredBitmap.length, executableBitmap.length)
|
|
1148
|
+
|
|
1149
|
+
for (let i = 0; i < length; i++) {
|
|
1150
|
+
let value = coveredBitmap[i] & executableBitmap[i]
|
|
1151
|
+
while (value) {
|
|
1152
|
+
value &= value - 1
|
|
1153
|
+
count++
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
return count
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
function getCoverageFileBitmap (bitmap) {
|
|
1161
|
+
if (!bitmap) return
|
|
1162
|
+
if (Buffer.isBuffer(bitmap)) return bitmap
|
|
1163
|
+
if (ArrayBuffer.isView(bitmap)) {
|
|
1164
|
+
return Buffer.from(bitmap.buffer, bitmap.byteOffset, bitmap.byteLength)
|
|
1165
|
+
}
|
|
1166
|
+
if (typeof bitmap === 'string') {
|
|
1167
|
+
return Buffer.from(bitmap, 'base64')
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
|
|
1171
|
+
function addCoverageFilesToMap (files, targetMap, rootDir) {
|
|
1172
|
+
for (const file of files) {
|
|
1173
|
+
const bitmap = getCoverageFileBitmap(file.bitmap)
|
|
1174
|
+
if (!bitmap) continue
|
|
1175
|
+
|
|
1176
|
+
const filename = rootDir ? getTestSuitePath(file.filename, rootDir) : file.filename
|
|
1177
|
+
targetMap.set(filename, mergeCoverageBitmaps(targetMap.get(filename), bitmap))
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
function addSkippedCoverageToMap (skippedCoverage, targetMap) {
|
|
1182
|
+
if (!skippedCoverage) return
|
|
1183
|
+
|
|
1184
|
+
for (const [filename, bitmap] of Object.entries(skippedCoverage)) {
|
|
1185
|
+
const coverageBitmap = getCoverageFileBitmap(bitmap)
|
|
1186
|
+
if (!coverageBitmap) continue
|
|
1187
|
+
targetMap.set(filename, mergeCoverageBitmaps(targetMap.get(filename), coverageBitmap))
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
function hasSkippedCoverage (skippedCoverage) {
|
|
1192
|
+
return skippedCoverage && typeof skippedCoverage === 'object' && Object.keys(skippedCoverage).length > 0
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
function getTestCoverageLinesPercentage (coverage, skippedCoverage, rootDir) {
|
|
1196
|
+
const executableLinesByFile = new Map()
|
|
1197
|
+
const coveredLinesByFile = new Map()
|
|
1198
|
+
|
|
1199
|
+
addCoverageFilesToMap(getExecutableFilesFromCoverage(coverage), executableLinesByFile, rootDir)
|
|
1200
|
+
addCoverageFilesToMap(getCoveredFilesFromCoverage(coverage), coveredLinesByFile, rootDir)
|
|
1201
|
+
addSkippedCoverageToMap(skippedCoverage, coveredLinesByFile)
|
|
1202
|
+
|
|
1203
|
+
let totalExecutableLines = 0
|
|
1204
|
+
let totalCoveredLines = 0
|
|
1205
|
+
|
|
1206
|
+
for (const [filename, executableLines] of executableLinesByFile) {
|
|
1207
|
+
totalExecutableLines += countBitmapBits(executableLines)
|
|
1208
|
+
totalCoveredLines += countCoveredExecutableBits(coveredLinesByFile.get(filename), executableLines)
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
return totalExecutableLines === 0 ? 0 : Math.floor((totalCoveredLines / totalExecutableLines) * 10_000) / 100
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
function isLineCoveredByBitmap (bitmap, line) {
|
|
1215
|
+
if (!Number.isSafeInteger(line) || line <= 0) return false
|
|
1216
|
+
|
|
1217
|
+
const byteIndex = line >> 3
|
|
1218
|
+
return byteIndex < bitmap.length && !!(bitmap[byteIndex] & (1 << (line % 8)))
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
function getSkippedCoverageByFilename (skippedCoverage) {
|
|
1222
|
+
const skippedCoverageByFilename = new Map()
|
|
1223
|
+
addSkippedCoverageToMap(skippedCoverage, skippedCoverageByFilename)
|
|
1224
|
+
return skippedCoverageByFilename
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
function applySkippedCoverageToFileCoverage (fileCoverage, skippedBitmap) {
|
|
1228
|
+
let updated = false
|
|
1229
|
+
for (const [statementId, statementLocation] of Object.entries(fileCoverage.data.statementMap)) {
|
|
1230
|
+
const startLine = statementLocation?.start?.line
|
|
1231
|
+
if (!isLineCoveredByBitmap(skippedBitmap, startLine)) continue
|
|
1232
|
+
if (fileCoverage.data.s[statementId] > 0) continue
|
|
1233
|
+
|
|
1234
|
+
fileCoverage.data.s[statementId] = 1
|
|
1235
|
+
updated = true
|
|
1236
|
+
}
|
|
1237
|
+
return updated
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
/**
|
|
1241
|
+
* Applies backend skipped-suite coverage to an Istanbul coverage map.
|
|
1242
|
+
* @param {object} coverage
|
|
1243
|
+
* @param {object} skippedCoverage
|
|
1244
|
+
* @param {string} [rootDir]
|
|
1245
|
+
* @returns {boolean}
|
|
1246
|
+
*/
|
|
1247
|
+
function applySkippedCoverageToCoverage (coverage, skippedCoverage, rootDir) {
|
|
1248
|
+
if (!hasSkippedCoverage(skippedCoverage)) return false
|
|
1249
|
+
|
|
1250
|
+
const coverageMap = getCoverageMap(coverage)
|
|
1251
|
+
const skippedCoverageByFilename = getSkippedCoverageByFilename(skippedCoverage)
|
|
1252
|
+
let matched = false
|
|
1253
|
+
|
|
1254
|
+
for (const filename of coverageMap.files()) {
|
|
1255
|
+
const relativeFilename = rootDir ? getTestSuitePath(filename, rootDir) : filename
|
|
1256
|
+
const skippedBitmap = skippedCoverageByFilename.get(relativeFilename)
|
|
1257
|
+
if (!skippedBitmap) continue
|
|
1258
|
+
|
|
1259
|
+
const fileCoverage = coverageMap.fileCoverageFor(filename)
|
|
1260
|
+
applySkippedCoverageToFileCoverage(fileCoverage, skippedBitmap)
|
|
1261
|
+
matched = true
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
return matched
|
|
1042
1265
|
}
|
|
1043
1266
|
|
|
1044
1267
|
function resetCoverage (coverage) {
|
|
@@ -10,16 +10,14 @@ const kinds = require('../../../../../ext/kinds')
|
|
|
10
10
|
const { ERROR_MESSAGE } = require('../../constants')
|
|
11
11
|
const TracingPlugin = require('../tracing')
|
|
12
12
|
const { storage } = require('../../../../datadog-core')
|
|
13
|
+
const legacyStorage = storage('legacy')
|
|
13
14
|
const urlFilter = require('./urlfilter')
|
|
14
15
|
const { createInferredProxySpan, finishInferredProxySpan } = require('./inferred_proxy')
|
|
15
16
|
const { extractURL, obfuscateQs, calculateHttpEndpoint } = require('./url')
|
|
16
17
|
|
|
17
|
-
let extractIp
|
|
18
|
-
|
|
19
18
|
const WEB = types.WEB
|
|
20
19
|
const SERVER = kinds.SERVER
|
|
21
20
|
const RESOURCE_NAME = tags.RESOURCE_NAME
|
|
22
|
-
const SERVICE_NAME = tags.SERVICE_NAME
|
|
23
21
|
const SPAN_TYPE = tags.SPAN_TYPE
|
|
24
22
|
const SPAN_KIND = tags.SPAN_KIND
|
|
25
23
|
const ERROR = tags.ERROR
|
|
@@ -35,7 +33,6 @@ const HTTP_CLIENT_IP = tags.HTTP_CLIENT_IP
|
|
|
35
33
|
const MANUAL_DROP = tags.MANUAL_DROP
|
|
36
34
|
|
|
37
35
|
const contexts = new WeakMap()
|
|
38
|
-
const ends = new WeakMap()
|
|
39
36
|
|
|
40
37
|
// TODO: change this to no longer rely on creating a dummy plugin to be able to access startSpan
|
|
41
38
|
function createWebPlugin (tracer, config = {}) {
|
|
@@ -67,7 +64,9 @@ const web = {
|
|
|
67
64
|
const middleware = getMiddlewareSetting(config)
|
|
68
65
|
const queryStringObfuscation = getQsObfuscator(config)
|
|
69
66
|
|
|
70
|
-
extractIp = config.clientIpEnabled
|
|
67
|
+
const extractIp = config.clientIpEnabled
|
|
68
|
+
? require('./ip_extractor').extractIp
|
|
69
|
+
: undefined
|
|
71
70
|
|
|
72
71
|
return {
|
|
73
72
|
...config,
|
|
@@ -77,6 +76,7 @@ const web = {
|
|
|
77
76
|
filter,
|
|
78
77
|
middleware,
|
|
79
78
|
queryStringObfuscation,
|
|
79
|
+
extractIp,
|
|
80
80
|
}
|
|
81
81
|
},
|
|
82
82
|
|
|
@@ -87,7 +87,7 @@ const web = {
|
|
|
87
87
|
if (!span) return
|
|
88
88
|
|
|
89
89
|
span.context()._name = `${name}.request`
|
|
90
|
-
span.context().
|
|
90
|
+
span.context().setTag('component', name)
|
|
91
91
|
span._integrationName = name
|
|
92
92
|
|
|
93
93
|
web.setConfig(req, config)
|
|
@@ -105,7 +105,7 @@ const web = {
|
|
|
105
105
|
}
|
|
106
106
|
|
|
107
107
|
if (config.service) {
|
|
108
|
-
|
|
108
|
+
web.plugin.setServiceName(span, config.service)
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
analyticsSampler.sample(span, config.measured, true)
|
|
@@ -126,7 +126,6 @@ const web = {
|
|
|
126
126
|
context.tracer = tracer
|
|
127
127
|
context.span = span
|
|
128
128
|
context.res = res
|
|
129
|
-
context.store = storage('legacy').getStore()
|
|
130
129
|
|
|
131
130
|
this.setConfig(req, config)
|
|
132
131
|
addRequestTags(context, this.TYPE)
|
|
@@ -204,7 +203,7 @@ const web = {
|
|
|
204
203
|
startServerlessSpanWithInferredProxy (tracer, config, name, req, traceCtx) {
|
|
205
204
|
const headers = req.headers
|
|
206
205
|
const reqCtx = contexts.get(req)
|
|
207
|
-
const store =
|
|
206
|
+
const store = legacyStorage.getStore()
|
|
208
207
|
const pubsubSpan = store?.span?._name === 'pubsub.push.receive' ? store.span : null
|
|
209
208
|
|
|
210
209
|
let childOf = pubsubSpan || tracer.extract(FORMAT_HTTP_HEADERS, headers)
|
|
@@ -225,9 +224,11 @@ const web = {
|
|
|
225
224
|
const context = contexts.get(req)
|
|
226
225
|
const { span, inferredProxySpan, error } = context
|
|
227
226
|
|
|
228
|
-
const
|
|
227
|
+
const spanContext = span.context()
|
|
228
|
+
const spanHasExistingError = spanContext.getTag('error') || spanContext.getTag(ERROR_MESSAGE)
|
|
229
229
|
const inferredSpanContext = inferredProxySpan?.context()
|
|
230
|
-
const inferredSpanHasExistingError = inferredSpanContext?.
|
|
230
|
+
const inferredSpanHasExistingError = inferredSpanContext?.getTag('error') ||
|
|
231
|
+
inferredSpanContext?.getTag(ERROR_MESSAGE)
|
|
231
232
|
|
|
232
233
|
const isValidStatusCode = context.config.validateStatus(statusCode)
|
|
233
234
|
|
|
@@ -266,7 +267,16 @@ const web = {
|
|
|
266
267
|
|
|
267
268
|
if (context.finished && !req.stream) return
|
|
268
269
|
|
|
270
|
+
// `addRequestTags` is idempotent: in the normal HTTP path it ran during
|
|
271
|
+
// `web.startSpan`. Serverless callers (e.g. Azure Functions) skip
|
|
272
|
+
// `web.startSpan` and rely on this call to do the request-side work.
|
|
269
273
|
addRequestTags(context, spanType)
|
|
274
|
+
// Configured-header tagging runs at finish time. Framework plugins
|
|
275
|
+
// (connect, express, ...) install their own config via `setFramework`
|
|
276
|
+
// after `web.startSpan` has already locked the http-plugin config in;
|
|
277
|
+
// tagging earlier would use the http-plugin's `headers` list and drop
|
|
278
|
+
// the framework's.
|
|
279
|
+
addRequestHeaders(context)
|
|
270
280
|
addResponseTags(context)
|
|
271
281
|
|
|
272
282
|
context.config.hooks.request(context.span, req, res)
|
|
@@ -293,11 +303,18 @@ const web = {
|
|
|
293
303
|
const writeHead = res.writeHead
|
|
294
304
|
|
|
295
305
|
return function (statusCode, statusMessage, headers) {
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
306
|
+
// CORS preflight tagging only matters for OPTIONS requests. Skip the
|
|
307
|
+
// getHeaders() spread + isOriginAllowed work entirely for the common
|
|
308
|
+
// GET / POST / etc. case. Node's http module passes `req.method`
|
|
309
|
+
// through unchanged, so all standard methods are uppercase; the
|
|
310
|
+
// `toLowerCase` fallback covers any non-standard caller.
|
|
311
|
+
if (req.method === 'OPTIONS' || req.method.toLowerCase() === 'options') {
|
|
312
|
+
headers = typeof statusMessage === 'string' ? headers : statusMessage
|
|
313
|
+
headers = { ...res.getHeaders(), ...headers }
|
|
314
|
+
|
|
315
|
+
if (isOriginAllowed(req, headers)) {
|
|
316
|
+
addAllowHeaders(req, res, headers)
|
|
317
|
+
}
|
|
301
318
|
}
|
|
302
319
|
|
|
303
320
|
return writeHead.apply(this, arguments)
|
|
@@ -306,34 +323,6 @@ const web = {
|
|
|
306
323
|
getContext (req) {
|
|
307
324
|
return contexts.get(req)
|
|
308
325
|
},
|
|
309
|
-
wrapRes (context, req, res, end) {
|
|
310
|
-
return function (...args) {
|
|
311
|
-
web.finishAll(context)
|
|
312
|
-
|
|
313
|
-
return end.apply(res, args)
|
|
314
|
-
}
|
|
315
|
-
},
|
|
316
|
-
wrapEnd (context) {
|
|
317
|
-
const req = context.req
|
|
318
|
-
const res = context.res
|
|
319
|
-
const end = res.end
|
|
320
|
-
|
|
321
|
-
res.writeHead = web.wrapWriteHead(context)
|
|
322
|
-
|
|
323
|
-
ends.set(res, this.wrapRes(context, req, res, end))
|
|
324
|
-
|
|
325
|
-
Object.defineProperty(res, 'end', {
|
|
326
|
-
configurable: true,
|
|
327
|
-
get () {
|
|
328
|
-
return ends.get(this)
|
|
329
|
-
},
|
|
330
|
-
set (value) {
|
|
331
|
-
ends.set(this, function (...args) {
|
|
332
|
-
return storage('legacy').run(context.store, value, ...args)
|
|
333
|
-
})
|
|
334
|
-
},
|
|
335
|
-
})
|
|
336
|
-
},
|
|
337
326
|
setRouteOrEndpointTag (req) {
|
|
338
327
|
const context = contexts.get(req)
|
|
339
328
|
|
|
@@ -379,6 +368,16 @@ function splitHeader (str) {
|
|
|
379
368
|
|
|
380
369
|
function addRequestTags (context, spanType) {
|
|
381
370
|
const { req, span, inferredProxySpan, config } = context
|
|
371
|
+
const spanContext = span.context()
|
|
372
|
+
|
|
373
|
+
// Idempotency guard. `addRequestTags` runs in `web.startSpan` for the
|
|
374
|
+
// normal HTTP path and again in `web.finishSpan`; without this guard the
|
|
375
|
+
// second call would re-extract the URL, re-obfuscate the query string,
|
|
376
|
+
// and re-publish five `tagsUpdateCh` events with the same values. The
|
|
377
|
+
// serverless path skips `startSpan` and lands here first, in which case
|
|
378
|
+
// HTTP_URL is unset and the work runs normally.
|
|
379
|
+
if (spanContext.hasTag(HTTP_URL)) return
|
|
380
|
+
|
|
382
381
|
const url = extractURL(req)
|
|
383
382
|
const type = spanType ?? WEB
|
|
384
383
|
|
|
@@ -391,8 +390,8 @@ function addRequestTags (context, spanType) {
|
|
|
391
390
|
})
|
|
392
391
|
|
|
393
392
|
// if client ip has already been set by appsec, no need to run it again
|
|
394
|
-
if (extractIp && !
|
|
395
|
-
const clientIp = extractIp(config, req)
|
|
393
|
+
if (config.extractIp && !spanContext.hasTag(HTTP_CLIENT_IP)) {
|
|
394
|
+
const clientIp = config.extractIp(config, req)
|
|
396
395
|
|
|
397
396
|
if (clientIp) {
|
|
398
397
|
span.setTag(HTTP_CLIENT_IP, clientIp)
|
|
@@ -410,8 +409,6 @@ function addRequestTags (context, spanType) {
|
|
|
410
409
|
if (securityTest !== undefined) {
|
|
411
410
|
span.setTag(`${HTTP_REQUEST_HEADERS}.x-datadog-security-test`, securityTest)
|
|
412
411
|
}
|
|
413
|
-
|
|
414
|
-
addHeaders(context)
|
|
415
412
|
}
|
|
416
413
|
|
|
417
414
|
function addResponseTags (context) {
|
|
@@ -426,14 +423,26 @@ function addResponseTags (context) {
|
|
|
426
423
|
[HTTP_STATUS_CODE]: res.statusCode,
|
|
427
424
|
})
|
|
428
425
|
|
|
426
|
+
addResponseHeaders(context)
|
|
427
|
+
|
|
429
428
|
web.addStatusError(req, res.statusCode)
|
|
430
429
|
}
|
|
431
430
|
|
|
432
431
|
function applyRouteOrEndpointTag (context) {
|
|
433
432
|
const { paths, span, config } = context
|
|
434
433
|
if (!span) return
|
|
435
|
-
const
|
|
436
|
-
|
|
434
|
+
const spanContext = span.context()
|
|
435
|
+
|
|
436
|
+
// AppSec calls `web.setRouteOrEndpointTag` from a pre-finish hook so the
|
|
437
|
+
// route/endpoint tags are available for API Security sampling, and the
|
|
438
|
+
// normal finish-time path runs this again. Either tag being present
|
|
439
|
+
// means the work has already been done; paths are stable between the
|
|
440
|
+
// two calls, so the second pass has nothing to add.
|
|
441
|
+
if (spanContext.hasTag(HTTP_ROUTE) || spanContext.hasTag(HTTP_ENDPOINT)) return
|
|
442
|
+
|
|
443
|
+
// Skip the `Array.prototype.join` builtin in the empty / single-segment
|
|
444
|
+
// cases; `paths[0]` covers both (`undefined` is falsy for the empty case).
|
|
445
|
+
const route = paths.length > 1 ? paths.join('') : paths[0]
|
|
437
446
|
|
|
438
447
|
if (route) {
|
|
439
448
|
// Use http.route from trusted framework instrumentation.
|
|
@@ -441,44 +450,49 @@ function applyRouteOrEndpointTag (context) {
|
|
|
441
450
|
return
|
|
442
451
|
}
|
|
443
452
|
|
|
444
|
-
if (!config.resourceRenamingEnabled
|
|
445
|
-
return
|
|
446
|
-
}
|
|
453
|
+
if (!config.resourceRenamingEnabled) return
|
|
447
454
|
|
|
448
455
|
// Route is unavailable, compute http.endpoint once.
|
|
449
|
-
const url =
|
|
456
|
+
const url = spanContext.getTag(HTTP_URL)
|
|
450
457
|
const endpoint = url ? calculateHttpEndpoint(url) : '/'
|
|
451
458
|
span.setTag(HTTP_ENDPOINT, endpoint)
|
|
452
459
|
}
|
|
453
460
|
|
|
454
461
|
function addResourceTag (context) {
|
|
455
462
|
const { req, span } = context
|
|
456
|
-
const
|
|
463
|
+
const spanContext = span.context()
|
|
457
464
|
|
|
458
|
-
if (
|
|
465
|
+
if (spanContext.getTag(RESOURCE_NAME)) return
|
|
459
466
|
|
|
460
|
-
const resource = [req.method,
|
|
467
|
+
const resource = [req.method, spanContext.getTag(HTTP_ROUTE)]
|
|
461
468
|
.filter(Boolean)
|
|
462
469
|
.join(' ')
|
|
463
470
|
|
|
464
471
|
span.setTag(RESOURCE_NAME, resource)
|
|
465
472
|
}
|
|
466
473
|
|
|
467
|
-
function
|
|
468
|
-
const { req,
|
|
474
|
+
function addRequestHeaders (context) {
|
|
475
|
+
const { req, config, span, inferredProxySpan } = context
|
|
469
476
|
|
|
470
477
|
for (const [key, tag] of config.headers) {
|
|
471
478
|
const reqHeader = req.headers[key]
|
|
472
|
-
const resHeader = res.getHeader(key)
|
|
473
|
-
|
|
474
479
|
if (reqHeader) {
|
|
475
|
-
|
|
476
|
-
|
|
480
|
+
const tagName = tag || `${HTTP_REQUEST_HEADERS}.${key}`
|
|
481
|
+
span.setTag(tagName, reqHeader)
|
|
482
|
+
inferredProxySpan?.setTag(tagName, reqHeader)
|
|
477
483
|
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
function addResponseHeaders (context) {
|
|
488
|
+
const { res, config, span, inferredProxySpan } = context
|
|
478
489
|
|
|
490
|
+
for (const [key, tag] of config.headers) {
|
|
491
|
+
const resHeader = res.getHeader(key)
|
|
479
492
|
if (resHeader) {
|
|
480
|
-
|
|
481
|
-
|
|
493
|
+
const tagName = tag || `${HTTP_RESPONSE_HEADERS}.${key}`
|
|
494
|
+
span.setTag(tagName, resHeader)
|
|
495
|
+
inferredProxySpan?.setTag(tagName, resHeader)
|
|
482
496
|
}
|
|
483
497
|
}
|
|
484
498
|
}
|
|
@@ -125,7 +125,7 @@ class PrioritySampler {
|
|
|
125
125
|
|
|
126
126
|
log.trace(span, auto)
|
|
127
127
|
|
|
128
|
-
const tag = this._getPriorityFromTags(context.
|
|
128
|
+
const tag = this._getPriorityFromTags(context.getTags(), context)
|
|
129
129
|
|
|
130
130
|
if (this.validate(tag)) {
|
|
131
131
|
context._sampling.priority = tag
|
|
@@ -300,7 +300,7 @@ class PrioritySampler {
|
|
|
300
300
|
* @returns {SamplingPriority}
|
|
301
301
|
*/
|
|
302
302
|
#getPriorityByAgent (context) {
|
|
303
|
-
const key = `service:${context.
|
|
303
|
+
const key = `service:${context.getTag(SERVICE_NAME)},env:${this._env}`
|
|
304
304
|
// TODO: Change underscored properties to private ones.
|
|
305
305
|
const sampler = this._samplers[key] || this._samplers[DEFAULT_KEY]
|
|
306
306
|
|
|
@@ -17,7 +17,7 @@ function findWebSpan (startedSpans, spanId) {
|
|
|
17
17
|
const ispan = startedSpans[i]
|
|
18
18
|
const context = ispan.context()
|
|
19
19
|
if (context._spanId === spanId) {
|
|
20
|
-
if (isWebServerSpan(context.
|
|
20
|
+
if (isWebServerSpan(context.getTags())) {
|
|
21
21
|
return true
|
|
22
22
|
}
|
|
23
23
|
spanId = context._parentId
|
|
@@ -268,7 +268,7 @@ class Profiler extends EventEmitter {
|
|
|
268
268
|
|
|
269
269
|
#onSpanFinish (span) {
|
|
270
270
|
const context = span.context()
|
|
271
|
-
const tags = context.
|
|
271
|
+
const tags = context.getTags()
|
|
272
272
|
if (!isWebServerSpan(tags)) return
|
|
273
273
|
|
|
274
274
|
const endpointName = endpointNameFromTags(tags)
|
|
@@ -247,6 +247,7 @@ class NativeWallProfiler {
|
|
|
247
247
|
// context -- we simply can't tell which one it might've been across all
|
|
248
248
|
// possible async context frames.
|
|
249
249
|
if (this.#asyncContextFrameEnabled) {
|
|
250
|
+
const current = this.#pprof.time.getContext()
|
|
250
251
|
if (this.#customLabelsActive) {
|
|
251
252
|
// Custom labels may be active in this async context. The current CPED
|
|
252
253
|
// context could be a 2-element array [profilingContext, customLabels].
|
|
@@ -254,7 +255,6 @@ class NativeWallProfiler {
|
|
|
254
255
|
// This flag is monotonic (once set, stays true) because async
|
|
255
256
|
// continuations from runWithLabels can fire at any time after the
|
|
256
257
|
// synchronous runWithLabels call has returned.
|
|
257
|
-
const current = this.#pprof.time.getContext()
|
|
258
258
|
if (Array.isArray(current)) {
|
|
259
259
|
if (current[0] !== sampleContext) {
|
|
260
260
|
this.#pprof.time.setContext([sampleContext, current[1]])
|
|
@@ -262,7 +262,13 @@ class NativeWallProfiler {
|
|
|
262
262
|
} else if (current !== sampleContext) {
|
|
263
263
|
this.#pprof.time.setContext(sampleContext)
|
|
264
264
|
}
|
|
265
|
-
|
|
265
|
+
// Every setContext() call in ACF mode allocates a fresh contextHolder
|
|
266
|
+
// (a node::ObjectWrap with its own v8::Global<v8::Value>) in the native
|
|
267
|
+
// profiler. Skip the call if the CPED already holds this sampleContext,
|
|
268
|
+
// which is the common case when the same span is repeatedly activated:
|
|
269
|
+
// #getProfilingContext caches profilingContext on span[ProfilingContext],
|
|
270
|
+
// so identity comparison short-circuits.
|
|
271
|
+
} else if (current !== sampleContext) {
|
|
266
272
|
this.#pprof.time.setContext(sampleContext)
|
|
267
273
|
}
|
|
268
274
|
} else {
|
|
@@ -294,7 +300,7 @@ class NativeWallProfiler {
|
|
|
294
300
|
|
|
295
301
|
let webTags
|
|
296
302
|
if (this.#endpointCollectionEnabled) {
|
|
297
|
-
const tags = context.
|
|
303
|
+
const tags = context.getTags()
|
|
298
304
|
if (isWebServerSpan(tags)) {
|
|
299
305
|
webTags = tags
|
|
300
306
|
} else {
|
|
@@ -333,7 +339,7 @@ class NativeWallProfiler {
|
|
|
333
339
|
if (!this.#started) return
|
|
334
340
|
const profilingContext = span[ProfilingContext]
|
|
335
341
|
if (profilingContext === undefined || profilingContext.webTags !== undefined) return
|
|
336
|
-
const tags = span.context().
|
|
342
|
+
const tags = span.context().getTags()
|
|
337
343
|
if (isWebServerSpan(tags)) {
|
|
338
344
|
profilingContext.webTags = tags
|
|
339
345
|
}
|