dd-trace
Advanced tools
Comparing version 3.56.0 to 3.57.0
{ | ||
"name": "dd-trace", | ||
"version": "3.56.0", | ||
"version": "3.57.0", | ||
"description": "Datadog APM tracing client for JavaScript", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -10,9 +10,14 @@ 'use strict' | ||
const req = new Request(input, init) | ||
const headers = req.headers | ||
const ctx = { req, headers } | ||
if (input instanceof Request) { | ||
const ctx = { req: input } | ||
return ch.tracePromise(() => fetch.call(this, req, { headers: ctx.headers }), ctx) | ||
return ch.tracePromise(() => fetch.call(this, input, init), ctx) | ||
} else { | ||
const req = new Request(input, init) | ||
const ctx = { req } | ||
return ch.tracePromise(() => fetch.call(this, req), ctx) | ||
} | ||
} | ||
} | ||
} |
@@ -13,2 +13,94 @@ 'use strict' | ||
const V4_PACKAGE_SHIMS = [ | ||
{ | ||
file: 'resources/chat/completions.js', | ||
targetClass: 'Completions', | ||
baseResource: 'chat.completions', | ||
methods: ['create'] | ||
}, | ||
{ | ||
file: 'resources/completions.js', | ||
targetClass: 'Completions', | ||
baseResource: 'completions', | ||
methods: ['create'] | ||
}, | ||
{ | ||
file: 'resources/embeddings.js', | ||
targetClass: 'Embeddings', | ||
baseResource: 'embeddings', | ||
methods: ['create'] | ||
}, | ||
{ | ||
file: 'resources/files.js', | ||
targetClass: 'Files', | ||
baseResource: 'files', | ||
methods: ['create', 'del', 'list', 'retrieve'] | ||
}, | ||
{ | ||
file: 'resources/files.js', | ||
targetClass: 'Files', | ||
baseResource: 'files', | ||
methods: ['retrieveContent'], | ||
versions: ['>=4.0.0 <4.17.1'] | ||
}, | ||
{ | ||
file: 'resources/files.js', | ||
targetClass: 'Files', | ||
baseResource: 'files', | ||
methods: ['content'], // replaced `retrieveContent` in v4.17.1 | ||
versions: ['>=4.17.1'] | ||
}, | ||
{ | ||
file: 'resources/images.js', | ||
targetClass: 'Images', | ||
baseResource: 'images', | ||
methods: ['createVariation', 'edit', 'generate'] | ||
}, | ||
{ | ||
file: 'resources/fine-tuning/jobs/jobs.js', | ||
targetClass: 'Jobs', | ||
baseResource: 'fine_tuning.jobs', | ||
methods: ['cancel', 'create', 'list', 'listEvents', 'retrieve'], | ||
versions: ['>=4.34.0'] // file location changed in 4.34.0 | ||
}, | ||
{ | ||
file: 'resources/fine-tuning/jobs.js', | ||
targetClass: 'Jobs', | ||
baseResource: 'fine_tuning.jobs', | ||
methods: ['cancel', 'create', 'list', 'listEvents', 'retrieve'], | ||
versions: ['>=4.1.0 <4.34.0'] | ||
}, | ||
{ | ||
file: 'resources/fine-tunes.js', // deprecated after 4.1.0 | ||
targetClass: 'FineTunes', | ||
baseResource: 'fine-tune', | ||
methods: ['cancel', 'create', 'list', 'listEvents', 'retrieve'], | ||
versions: ['>=4.0.0 <4.1.0'] | ||
}, | ||
{ | ||
file: 'resources/models.js', | ||
targetClass: 'Models', | ||
baseResource: 'models', | ||
methods: ['del', 'list', 'retrieve'] | ||
}, | ||
{ | ||
file: 'resources/moderations.js', | ||
targetClass: 'Moderations', | ||
baseResource: 'moderations', | ||
methods: ['create'] | ||
}, | ||
{ | ||
file: 'resources/audio/transcriptions.js', | ||
targetClass: 'Transcriptions', | ||
baseResource: 'audio.transcriptions', | ||
methods: ['create'] | ||
}, | ||
{ | ||
file: 'resources/audio/translations.js', | ||
targetClass: 'Translations', | ||
baseResource: 'audio.translations', | ||
methods: ['create'] | ||
} | ||
] | ||
addHook({ name: 'openai', file: 'dist/api.js', versions: ['>=3.0.0 <4'] }, exports => { | ||
@@ -52,1 +144,58 @@ const methodNames = Object.getOwnPropertyNames(exports.OpenAIApi.prototype) | ||
}) | ||
for (const shim of V4_PACKAGE_SHIMS) { | ||
const { file, targetClass, baseResource, methods } = shim | ||
addHook({ name: 'openai', file, versions: shim.versions || ['>=4'] }, exports => { | ||
const targetPrototype = exports[targetClass].prototype | ||
for (const methodName of methods) { | ||
shimmer.wrap(targetPrototype, methodName, methodFn => function () { | ||
if (!startCh.hasSubscribers) { | ||
return methodFn.apply(this, arguments) | ||
} | ||
const client = this._client || this.client | ||
startCh.publish({ | ||
methodName: `${baseResource}.${methodName}`, | ||
args: arguments, | ||
basePath: client.baseURL, | ||
apiKey: client.apiKey | ||
}) | ||
const apiProm = methodFn.apply(this, arguments) | ||
// wrapping `parse` avoids problematic wrapping of `then` when trying to call | ||
// `withResponse` in userland code after. This way, we can return the whole `APIPromise` | ||
shimmer.wrap(apiProm, 'parse', origApiPromParse => function () { | ||
return origApiPromParse.apply(this, arguments) | ||
// the original response is wrapped in a promise, so we need to unwrap it | ||
.then(body => Promise.all([this.responsePromise, body])) | ||
.then(([{ response, options }, body]) => { | ||
finishCh.publish({ | ||
headers: response.headers, | ||
body, | ||
path: response.url, | ||
method: options.method | ||
}) | ||
return body | ||
}) | ||
.catch(err => { | ||
errorCh.publish({ err }) | ||
throw err | ||
}) | ||
.finally(() => { | ||
// maybe we don't want to unwrap here in case the promise is re-used? | ||
// other hand: we want to avoid resource leakage | ||
shimmer.unwrap(apiProm, 'parse') | ||
}) | ||
}) | ||
return apiProm | ||
}) | ||
} | ||
return exports | ||
}) | ||
} |
@@ -20,4 +20,7 @@ 'use strict' | ||
ctx.headers = headers | ||
ctx.req = new globalThis.Request(req, { headers }) | ||
for (const name in headers) { | ||
if (!req.headers.has(name)) { | ||
req.headers.set(name, headers[name]) | ||
} | ||
} | ||
@@ -24,0 +27,0 @@ return store |
@@ -87,3 +87,3 @@ 'use strict' | ||
// createChatCompletion, createCompletion, createImage, createImageEdit, createTranscription, createTranslation | ||
if ('prompt' in payload) { | ||
if (payload.prompt) { | ||
const prompt = payload.prompt | ||
@@ -103,3 +103,3 @@ store.prompt = prompt | ||
// createEdit, createEmbedding, createModeration | ||
if ('input' in payload) { | ||
if (payload.input) { | ||
const normalized = normalizeStringOrTokenArray(payload.input, false) | ||
@@ -119,2 +119,4 @@ tags['openai.request.input'] = truncateText(normalized) | ||
case 'createFineTune': | ||
case 'fine_tuning.jobs.create': | ||
case 'fine-tune.create': | ||
createFineTuneRequestExtraction(tags, payload) | ||
@@ -124,4 +126,7 @@ break | ||
case 'createImage': | ||
case 'images.generate': | ||
case 'createImageEdit': | ||
case 'images.edit': | ||
case 'createImageVariation': | ||
case 'images.createVariation': | ||
commonCreateImageRequestExtraction(tags, payload, store) | ||
@@ -131,2 +136,3 @@ break | ||
case 'createChatCompletion': | ||
case 'chat.completions.create': | ||
createChatCompletionRequestExtraction(tags, payload, store) | ||
@@ -136,3 +142,5 @@ break | ||
case 'createFile': | ||
case 'files.create': | ||
case 'retrieveFile': | ||
case 'files.retrieve': | ||
commonFileRequestExtraction(tags, payload) | ||
@@ -142,3 +150,5 @@ break | ||
case 'createTranscription': | ||
case 'audio.transcriptions.create': | ||
case 'createTranslation': | ||
case 'audio.translations.create': | ||
commonCreateAudioRequestExtraction(tags, payload, store) | ||
@@ -148,2 +158,3 @@ break | ||
case 'retrieveModel': | ||
case 'models.retrieve': | ||
retrieveModelRequestExtraction(tags, payload) | ||
@@ -153,5 +164,12 @@ break | ||
case 'listFineTuneEvents': | ||
case 'fine_tuning.jobs.listEvents': | ||
case 'fine-tune.listEvents': | ||
case 'retrieveFineTune': | ||
case 'fine_tuning.jobs.retrieve': | ||
case 'fine-tune.retrieve': | ||
case 'deleteModel': | ||
case 'models.del': | ||
case 'cancelFineTune': | ||
case 'fine_tuning.jobs.cancel': | ||
case 'fine-tune.cancel': | ||
commonLookupFineTuneRequestExtraction(tags, payload) | ||
@@ -161,2 +179,3 @@ break | ||
case 'createEdit': | ||
case 'edits.create': | ||
createEditRequestExtraction(tags, payload, store) | ||
@@ -170,2 +189,6 @@ break | ||
finish ({ headers, body, method, path }) { | ||
if (headers.constructor.name === 'Headers') { | ||
headers = Object.fromEntries(headers) | ||
} | ||
const span = this.activeSpan | ||
@@ -179,2 +202,7 @@ const methodName = span._spanContext._tags['resource.name'] | ||
if (path.startsWith('https://') || path.startsWith('http://')) { | ||
// basic checking for if the path was set as a full URL | ||
// not using a full regex as it will likely be "https://api.openai.com/..." | ||
path = new URL(path).pathname | ||
} | ||
const endpoint = lookupOperationEndpoint(methodName, path) | ||
@@ -184,3 +212,3 @@ | ||
'openai.request.endpoint': endpoint, | ||
'openai.request.method': method, | ||
'openai.request.method': method.toUpperCase(), | ||
@@ -236,3 +264,3 @@ 'openai.organization.id': body.organization_id, // only available in fine-tunes endpoints | ||
if (body && ('usage' in body)) { | ||
if (body && body.usage) { | ||
const promptTokens = body.usage.prompt_tokens | ||
@@ -245,15 +273,15 @@ const completionTokens = body.usage.completion_tokens | ||
if ('x-ratelimit-limit-requests' in headers) { | ||
if (headers['x-ratelimit-limit-requests']) { | ||
this.metrics.gauge('openai.ratelimit.requests', Number(headers['x-ratelimit-limit-requests']), tags) | ||
} | ||
if ('x-ratelimit-remaining-requests' in headers) { | ||
if (headers['x-ratelimit-remaining-requests']) { | ||
this.metrics.gauge('openai.ratelimit.remaining.requests', Number(headers['x-ratelimit-remaining-requests']), tags) | ||
} | ||
if ('x-ratelimit-limit-tokens' in headers) { | ||
if (headers['x-ratelimit-limit-tokens']) { | ||
this.metrics.gauge('openai.ratelimit.tokens', Number(headers['x-ratelimit-limit-tokens']), tags) | ||
} | ||
if ('x-ratelimit-remaining-tokens' in headers) { | ||
if (headers['x-ratelimit-remaining-tokens']) { | ||
this.metrics.gauge('openai.ratelimit.remaining.tokens', Number(headers['x-ratelimit-remaining-tokens']), tags) | ||
@@ -293,6 +321,6 @@ } | ||
const message = payload.messages[i] | ||
tags[`openai.request.${i}.content`] = truncateText(message.content) | ||
tags[`openai.request.${i}.role`] = message.role | ||
tags[`openai.request.${i}.name`] = message.name | ||
tags[`openai.request.${i}.finish_reason`] = message.finish_reason | ||
tags[`openai.request.messages.${i}.content`] = truncateText(message.content) | ||
tags[`openai.request.messages.${i}.role`] = message.role | ||
tags[`openai.request.messages.${i}.name`] = message.name | ||
tags[`openai.request.messages.${i}.finish_reason`] = message.finish_reason | ||
} | ||
@@ -303,4 +331,5 @@ } | ||
// createImageEdit, createImageVariation | ||
if (payload.file && typeof payload.file === 'object' && payload.file.path) { | ||
const file = path.basename(payload.file.path) | ||
const img = payload.file || payload.image | ||
if (img && typeof img === 'object' && img.path) { | ||
const file = path.basename(img.path) | ||
tags['openai.request.image'] = file | ||
@@ -325,2 +354,3 @@ store.file = file | ||
case 'createModeration': | ||
case 'moderations.create': | ||
createModerationResponseExtraction(tags, body) | ||
@@ -330,4 +360,7 @@ break | ||
case 'createCompletion': | ||
case 'completions.create': | ||
case 'createChatCompletion': | ||
case 'chat.completions.create': | ||
case 'createEdit': | ||
case 'edits.create': | ||
commonCreateResponseExtraction(tags, body, store) | ||
@@ -337,4 +370,9 @@ break | ||
case 'listFiles': | ||
case 'files.list': | ||
case 'listFineTunes': | ||
case 'fine_tuning.jobs.list': | ||
case 'fine-tune.list': | ||
case 'listFineTuneEvents': | ||
case 'fine_tuning.jobs.listEvents': | ||
case 'fine-tune.listEvents': | ||
commonListCountResponseExtraction(tags, body) | ||
@@ -344,2 +382,3 @@ break | ||
case 'createEmbedding': | ||
case 'embeddings.create': | ||
createEmbeddingResponseExtraction(tags, body) | ||
@@ -349,3 +388,5 @@ break | ||
case 'createFile': | ||
case 'files.create': | ||
case 'retrieveFile': | ||
case 'files.retrieve': | ||
createRetrieveFileResponseExtraction(tags, body) | ||
@@ -355,2 +396,3 @@ break | ||
case 'deleteFile': | ||
case 'files.del': | ||
deleteFileResponseExtraction(tags, body) | ||
@@ -360,2 +402,4 @@ break | ||
case 'downloadFile': | ||
case 'files.retrieveContent': | ||
case 'files.content': | ||
downloadFileResponseExtraction(tags, body) | ||
@@ -365,4 +409,10 @@ break | ||
case 'createFineTune': | ||
case 'fine_tuning.jobs.create': | ||
case 'fine-tune.create': | ||
case 'retrieveFineTune': | ||
case 'fine_tuning.jobs.retrieve': | ||
case 'fine-tune.retrieve': | ||
case 'cancelFineTune': | ||
case 'fine_tuning.jobs.cancel': | ||
case 'fine-tune.cancel': | ||
commonFineTuneResponseExtraction(tags, body) | ||
@@ -372,3 +422,5 @@ break | ||
case 'createTranscription': | ||
case 'audio.transcriptions.create': | ||
case 'createTranslation': | ||
case 'audio.translations.create': | ||
createAudioResponseExtraction(tags, body) | ||
@@ -378,4 +430,7 @@ break | ||
case 'createImage': | ||
case 'images.generate': | ||
case 'createImageEdit': | ||
case 'images.edit': | ||
case 'createImageVariation': | ||
case 'images.createVariation': | ||
commonImageResponseExtraction(tags, body) | ||
@@ -385,2 +440,3 @@ break | ||
case 'listModels': | ||
case 'models.list': | ||
listModelsResponseExtraction(tags, body) | ||
@@ -390,2 +446,3 @@ break | ||
case 'retrieveModel': | ||
case 'models.retrieve': | ||
retrieveModelResponseExtraction(tags, body) | ||
@@ -463,11 +520,15 @@ break | ||
tags['openai.response.fine_tuned_model'] = body.fine_tuned_model | ||
if (body.hyperparams) { | ||
tags['openai.response.hyperparams.n_epochs'] = body.hyperparams.n_epochs | ||
tags['openai.response.hyperparams.batch_size'] = body.hyperparams.batch_size | ||
tags['openai.response.hyperparams.prompt_loss_weight'] = body.hyperparams.prompt_loss_weight | ||
tags['openai.response.hyperparams.learning_rate_multiplier'] = body.hyperparams.learning_rate_multiplier | ||
const hyperparams = body.hyperparams || body.hyperparameters | ||
const hyperparamsKey = body.hyperparams ? 'hyperparams' : 'hyperparameters' | ||
if (hyperparams) { | ||
tags[`openai.response.${hyperparamsKey}.n_epochs`] = hyperparams.n_epochs | ||
tags[`openai.response.${hyperparamsKey}.batch_size`] = hyperparams.batch_size | ||
tags[`openai.response.${hyperparamsKey}.prompt_loss_weight`] = hyperparams.prompt_loss_weight | ||
tags[`openai.response.${hyperparamsKey}.learning_rate_multiplier`] = hyperparams.learning_rate_multiplier | ||
} | ||
tags['openai.response.training_files_count'] = defensiveArrayLength(body.training_files) | ||
tags['openai.response.training_files_count'] = defensiveArrayLength(body.training_files || body.training_file) | ||
tags['openai.response.result_files_count'] = defensiveArrayLength(body.result_files) | ||
tags['openai.response.validation_files_count'] = defensiveArrayLength(body.validation_files) | ||
tags['openai.response.validation_files_count'] = defensiveArrayLength(body.validation_files || body.validation_file) | ||
tags['openai.response.updated_at'] = body.updated_at | ||
@@ -561,14 +622,27 @@ tags['openai.response.status'] = body.status | ||
for (let i = 0; i < body.choices.length; i++) { | ||
const choice = body.choices[i] | ||
tags[`openai.response.choices.${i}.finish_reason`] = choice.finish_reason | ||
tags[`openai.response.choices.${i}.logprobs`] = ('logprobs' in choice) ? 'returned' : undefined | ||
tags[`openai.response.choices.${i}.text`] = truncateText(choice.text) | ||
for (let choiceIdx = 0; choiceIdx < body.choices.length; choiceIdx++) { | ||
const choice = body.choices[choiceIdx] | ||
// logprobs can be nullm and we still want to tag it as 'returned' even when set to 'null' | ||
const specifiesLogProb = Object.keys(choice).indexOf('logprobs') !== -1 | ||
tags[`openai.response.choices.${choiceIdx}.finish_reason`] = choice.finish_reason | ||
tags[`openai.response.choices.${choiceIdx}.logprobs`] = specifiesLogProb ? 'returned' : undefined | ||
tags[`openai.response.choices.${choiceIdx}.text`] = truncateText(choice.text) | ||
// createChatCompletion only | ||
if ('message' in choice) { | ||
if (choice.message) { | ||
const message = choice.message | ||
tags[`openai.response.choices.${i}.message.role`] = message.role | ||
tags[`openai.response.choices.${i}.message.content`] = truncateText(message.content) | ||
tags[`openai.response.choices.${i}.message.name`] = truncateText(message.name) | ||
tags[`openai.response.choices.${choiceIdx}.message.role`] = message.role | ||
tags[`openai.response.choices.${choiceIdx}.message.content`] = truncateText(message.content) | ||
tags[`openai.response.choices.${choiceIdx}.message.name`] = truncateText(message.name) | ||
if (message.tool_calls) { | ||
const toolCalls = message.tool_calls | ||
for (let toolIdx = 0; toolIdx < toolCalls.length; toolIdx++) { | ||
tags[`openai.response.choices.${choiceIdx}.message.tool_calls.${toolIdx}.name`] = | ||
toolCalls[toolIdx].function.name | ||
tags[`openai.response.choices.${choiceIdx}.message.tool_calls.${toolIdx}.arguments`] = | ||
toolCalls[toolIdx].function.arguments | ||
} | ||
} | ||
} | ||
@@ -611,6 +685,19 @@ } | ||
case 'downloadFile': | ||
case 'files.retrieveContent': | ||
case 'files.content': | ||
return { file: body } | ||
} | ||
return typeof body === 'object' ? body : {} | ||
const type = typeof body | ||
if (type === 'string') { | ||
try { | ||
return JSON.parse(body) | ||
} catch { | ||
return body | ||
} | ||
} else if (type === 'object') { | ||
return body | ||
} else { | ||
return {} | ||
} | ||
} | ||
@@ -622,20 +709,35 @@ | ||
case 'deleteModel': | ||
case 'models.del': | ||
case 'retrieveModel': | ||
case 'models.retrieve': | ||
return '/v1/models/*' | ||
case 'deleteFile': | ||
case 'files.del': | ||
case 'retrieveFile': | ||
case 'files.retrieve': | ||
return '/v1/files/*' | ||
case 'downloadFile': | ||
case 'files.retrieveContent': | ||
case 'files.content': | ||
return '/v1/files/*/content' | ||
case 'retrieveFineTune': | ||
case 'fine-tune.retrieve': | ||
return '/v1/fine-tunes/*' | ||
case 'fine_tuning.jobs.retrieve': | ||
return '/v1/fine_tuning/jobs/*' | ||
case 'listFineTuneEvents': | ||
case 'fine-tune.listEvents': | ||
return '/v1/fine-tunes/*/events' | ||
case 'fine_tuning.jobs.listEvents': | ||
return '/v1/fine_tuning/jobs/*/events' | ||
case 'cancelFineTune': | ||
case 'fine-tune.cancel': | ||
return '/v1/fine-tunes/*/cancel' | ||
case 'fine_tuning.jobs.cancel': | ||
return '/v1/fine_tuning/jobs/*/cancel' | ||
} | ||
@@ -654,4 +756,8 @@ | ||
case 'listModels': | ||
case 'models.list': | ||
case 'listFiles': | ||
case 'files.list': | ||
case 'listFineTunes': | ||
case 'fine_tuning.jobs.list': | ||
case 'fine-tune.list': | ||
// no argument | ||
@@ -661,2 +767,3 @@ return {} | ||
case 'retrieveModel': | ||
case 'models.retrieve': | ||
return { id: args[0] } | ||
@@ -671,7 +778,13 @@ | ||
case 'deleteFile': | ||
case 'files.del': | ||
case 'retrieveFile': | ||
case 'files.retrieve': | ||
case 'downloadFile': | ||
case 'files.retrieveContent': | ||
case 'files.content': | ||
return { file_id: args[0] } | ||
case 'listFineTuneEvents': | ||
case 'fine_tuning.jobs.listEvents': | ||
case 'fine-tune.listEvents': | ||
return { | ||
@@ -683,4 +796,9 @@ fine_tune_id: args[0], | ||
case 'retrieveFineTune': | ||
case 'fine_tuning.jobs.retrieve': | ||
case 'fine-tune.retrieve': | ||
case 'deleteModel': | ||
case 'models.del': | ||
case 'cancelFineTune': | ||
case 'fine_tuning.jobs.cancel': | ||
case 'fine-tune.cancel': | ||
return { fine_tune_id: args[0] } | ||
@@ -742,5 +860,14 @@ | ||
function defensiveArrayLength (maybeArray) { | ||
return Array.isArray(maybeArray) ? maybeArray.length : undefined | ||
if (maybeArray) { | ||
if (Array.isArray(maybeArray)) { | ||
return maybeArray.length | ||
} else { | ||
// case of a singular item (ie body.training_file vs body.training_files) | ||
return 1 | ||
} | ||
} | ||
return undefined | ||
} | ||
module.exports = OpenApiPlugin |
@@ -7,3 +7,3 @@ 'use strict' | ||
function taintObject (iastContext, object, type, keyTainting, keyType) { | ||
function taintObject (iastContext, object, type) { | ||
let result = object | ||
@@ -26,5 +26,2 @@ const transactionId = iastContext?.[IAST_TRANSACTION_ID] | ||
result = tainted | ||
} else if (keyTainting && key) { | ||
const taintedProperty = TaintedUtils.newTaintedString(transactionId, key, property, keyType) | ||
parent[taintedProperty] = tainted | ||
} else { | ||
@@ -39,7 +36,2 @@ parent[key] = tainted | ||
} | ||
if (parent && keyTainting && key) { | ||
const taintedProperty = TaintedUtils.newTaintedString(transactionId, key, property, keyType) | ||
parent[taintedProperty] = value | ||
} | ||
} | ||
@@ -46,0 +38,0 @@ } catch (e) { |
@@ -98,8 +98,10 @@ 'use strict' | ||
const iastContext = getIastContext(storage.getStore()) | ||
taintObject(iastContext, target, HTTP_REQUEST_COOKIE_VALUE, true, HTTP_REQUEST_COOKIE_NAME) | ||
// Prevent tainting cookie names since it leads to taint literal string with same value. | ||
taintObject(iastContext, target, HTTP_REQUEST_COOKIE_VALUE) | ||
} | ||
taintHeaders (headers, iastContext) { | ||
// Prevent tainting header names since it leads to taint literal string with same value. | ||
this.execSource({ | ||
handler: () => taintObject(iastContext, headers, HTTP_REQUEST_HEADER_VALUE, true, HTTP_REQUEST_HEADER_NAME), | ||
handler: () => taintObject(iastContext, headers, HTTP_REQUEST_HEADER_VALUE), | ||
tags: REQ_HEADER_TAGS, | ||
@@ -106,0 +108,0 @@ iastContext |
@@ -11,3 +11,3 @@ 'use strict' | ||
function enable (config) { | ||
function enable (config, appsec) { | ||
rc = new RemoteConfigManager(config) | ||
@@ -35,3 +35,3 @@ rc.updateCapabilities(RemoteConfigCapabilities.APM_TRACING_CUSTOM_TAGS, true) | ||
if (activation === Activation.ONECLICK) { | ||
enableOrDisableAppsec(action, rcConfig, config) | ||
enableOrDisableAppsec(action, rcConfig, config, appsec) | ||
} | ||
@@ -46,3 +46,3 @@ | ||
function enableOrDisableAppsec (action, rcConfig, config) { | ||
function enableOrDisableAppsec (action, rcConfig, config, appsec) { | ||
if (typeof rcConfig.asm?.enabled === 'boolean') { | ||
@@ -58,5 +58,5 @@ let shouldEnable | ||
if (shouldEnable) { | ||
require('..').enable(config) | ||
appsec.enable(config) | ||
} else { | ||
require('..').disable() | ||
appsec.disable() | ||
} | ||
@@ -63,0 +63,0 @@ } |
@@ -18,2 +18,17 @@ 'use strict' | ||
class LazyModule { | ||
constructor (provider) { | ||
this.provider = provider | ||
} | ||
enable (...args) { | ||
this.module = this.provider() | ||
this.module.enable(...args) | ||
} | ||
disable () { | ||
this.module?.disable() | ||
} | ||
} | ||
class Tracer extends NoopProxy { | ||
@@ -28,2 +43,8 @@ constructor () { | ||
this._tracingInitialized = false | ||
// these requires must work with esm bundler | ||
this._modules = { | ||
appsec: new LazyModule(() => require('./appsec')), | ||
iast: new LazyModule(() => require('./appsec/iast')) | ||
} | ||
} | ||
@@ -63,3 +84,3 @@ | ||
if (config.remoteConfig.enabled && !config.isCiVisibility) { | ||
const rc = remoteConfig.enable(config) | ||
const rc = remoteConfig.enable(config, this._modules.appsec) | ||
@@ -119,5 +140,4 @@ rc.on('APM_TRACING', (action, conf) => { | ||
if (config.tracing !== false) { | ||
// dirty require for now so zero appsec code is executed unless explicitly enabled | ||
if (config.appsec.enabled) { | ||
require('./appsec').enable(config) | ||
this._modules.appsec.enable(config) | ||
} | ||
@@ -130,7 +150,7 @@ if (!this._tracingInitialized) { | ||
if (config.iast.enabled) { | ||
require('./appsec/iast').enable(config, this._tracer) | ||
this._modules.iast.enable(config, this._tracer) | ||
} | ||
} else if (this._tracingInitialized) { | ||
require('./appsec').disable() | ||
require('./appsec/iast').disable() | ||
this._modules.appsec.disable() | ||
this._modules.iast.disable() | ||
} | ||
@@ -137,0 +157,0 @@ |
1761376
51033
24