dd-trace 5.97.0 → 5.99.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 +0 -1
- package/ext/tags.js +1 -0
- package/index.d.ts +35 -3
- package/package.json +48 -46
- package/packages/datadog-instrumentations/src/crypto.js +45 -0
- package/packages/datadog-instrumentations/src/cucumber.js +65 -3
- package/packages/datadog-instrumentations/src/cypress-config.js +153 -53
- package/packages/datadog-instrumentations/src/dns.js +24 -56
- package/packages/datadog-instrumentations/src/graphql.js +1 -1
- package/packages/datadog-instrumentations/src/helpers/callback-instrumentor.js +74 -0
- package/packages/datadog-instrumentations/src/helpers/check-require-cache.js +4 -1
- package/packages/datadog-instrumentations/src/helpers/hooks.js +2 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/compiler.js +10 -3
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/index.js +1 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/instrumentations/modelcontextprotocol-sdk.js +59 -0
- package/packages/datadog-instrumentations/src/helpers/rewriter/transforms.js +11 -2
- package/packages/datadog-instrumentations/src/jest.js +104 -12
- package/packages/datadog-instrumentations/src/mocha/utils.js +8 -0
- package/packages/datadog-instrumentations/src/modelcontextprotocol-sdk.js +7 -0
- package/packages/datadog-instrumentations/src/pino.js +4 -28
- package/packages/datadog-instrumentations/src/playwright-browser-scripts.js +27 -0
- package/packages/datadog-instrumentations/src/playwright.js +5 -17
- package/packages/datadog-instrumentations/src/redis.js +12 -6
- package/packages/datadog-instrumentations/src/stripe.js +38 -24
- package/packages/datadog-instrumentations/src/vitest.js +32 -4
- package/packages/datadog-instrumentations/src/zlib.js +29 -0
- package/packages/datadog-plugin-aws-sdk/src/base.js +2 -3
- package/packages/datadog-plugin-aws-sdk/src/services/dynamodb.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/eventbridge.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/kinesis.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/redshift.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sns.js +1 -0
- package/packages/datadog-plugin-aws-sdk/src/services/sqs.js +1 -0
- package/packages/datadog-plugin-azure-event-hubs/src/producer.js +8 -15
- package/packages/datadog-plugin-azure-service-bus/src/producer.js +4 -9
- package/packages/datadog-plugin-cucumber/src/index.js +8 -2
- package/packages/datadog-plugin-cypress/src/cypress-plugin.js +114 -6
- package/packages/datadog-plugin-cypress/src/index.js +59 -2
- package/packages/datadog-plugin-cypress/src/source-map-utils.js +48 -1
- package/packages/datadog-plugin-fs/src/index.js +1 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/consumer.js +2 -1
- package/packages/datadog-plugin-google-cloud-pubsub/src/pubsub-push-subscription.js +2 -7
- package/packages/datadog-plugin-http/src/client.js +1 -1
- package/packages/datadog-plugin-http/src/server.js +21 -13
- package/packages/datadog-plugin-http2/src/client.js +1 -1
- package/packages/datadog-plugin-http2/src/server.js +10 -2
- package/packages/datadog-plugin-jest/src/index.js +2 -2
- package/packages/datadog-plugin-mocha/src/index.js +1 -2
- package/packages/datadog-plugin-modelcontextprotocol-sdk/src/index.js +24 -0
- package/packages/datadog-plugin-modelcontextprotocol-sdk/src/tracing.js +55 -0
- package/packages/datadog-plugin-mongodb-core/src/index.js +4 -9
- package/packages/datadog-plugin-mysql/src/index.js +1 -1
- package/packages/datadog-plugin-next/src/index.js +8 -2
- package/packages/datadog-plugin-pg/src/index.js +1 -1
- package/packages/datadog-plugin-playwright/src/index.js +2 -3
- package/packages/datadog-plugin-tedious/src/index.js +1 -1
- package/packages/datadog-plugin-vitest/src/index.js +14 -6
- package/packages/datadog-plugin-ws/src/close.js +3 -1
- package/packages/datadog-plugin-ws/src/producer.js +2 -0
- package/packages/datadog-plugin-ws/src/receiver.js +2 -1
- package/packages/dd-trace/src/aiguard/channels.js +8 -0
- package/packages/dd-trace/src/aiguard/index.js +7 -3
- package/packages/dd-trace/src/aiguard/sdk.js +66 -22
- package/packages/dd-trace/src/aiguard/tags.js +1 -0
- package/packages/dd-trace/src/appsec/blocked_templates.js +4 -3
- package/packages/dd-trace/src/appsec/blocking.js +62 -34
- package/packages/dd-trace/src/appsec/graphql.js +6 -6
- package/packages/dd-trace/src/appsec/index.js +9 -11
- package/packages/dd-trace/src/appsec/rasp/command_injection.js +4 -5
- package/packages/dd-trace/src/appsec/rasp/lfi.js +8 -4
- package/packages/dd-trace/src/appsec/rasp/sql_injection.js +5 -10
- package/packages/dd-trace/src/appsec/rasp/ssrf.js +5 -6
- package/packages/dd-trace/src/appsec/recommended.json +2438 -13
- package/packages/dd-trace/src/appsec/reporter.js +6 -5
- package/packages/dd-trace/src/appsec/sdk/set_user.js +1 -1
- package/packages/dd-trace/src/appsec/sdk/track_event.js +5 -5
- package/packages/dd-trace/src/appsec/sdk/user_blocking.js +6 -10
- package/packages/dd-trace/src/appsec/sdk/utils.js +4 -2
- package/packages/dd-trace/src/appsec/store.js +50 -0
- package/packages/dd-trace/src/appsec/waf/index.js +3 -5
- package/packages/dd-trace/src/ci-visibility/early-flake-detection/get-known-tests.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/coverage-writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/di-logs-writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/agentless/writer.js +2 -2
- package/packages/dd-trace/src/ci-visibility/exporters/git/git_metadata.js +3 -4
- package/packages/dd-trace/src/ci-visibility/intelligent-test-runner/get-skippable-suites.js +2 -2
- package/packages/dd-trace/src/ci-visibility/log-submission/log-submission-plugin.js +4 -5
- package/packages/dd-trace/src/ci-visibility/requests/fs-cache.js +3 -4
- package/packages/dd-trace/src/ci-visibility/requests/get-library-configuration.js +6 -6
- package/packages/dd-trace/src/ci-visibility/requests/upload-coverage-report.js +2 -2
- package/packages/dd-trace/src/ci-visibility/test-management/get-test-management-tests.js +2 -2
- package/packages/dd-trace/src/config/config-types.d.ts +0 -4
- package/packages/dd-trace/src/config/defaults.js +10 -11
- package/packages/dd-trace/src/config/generated-config-types.d.ts +14 -8
- package/packages/dd-trace/src/config/index.js +49 -32
- package/packages/dd-trace/src/config/parsers.js +26 -9
- package/packages/dd-trace/src/config/supported-configurations.json +86 -33
- package/packages/dd-trace/src/constants.js +1 -0
- package/packages/dd-trace/src/debugger/config.js +2 -0
- package/packages/dd-trace/src/debugger/devtools_client/send.js +25 -5
- package/packages/dd-trace/src/debugger/devtools_client/snapshot/processor.js +5 -2
- package/packages/dd-trace/src/encode/0.4.js +11 -11
- package/packages/dd-trace/src/encode/span-stats.js +4 -1
- package/packages/dd-trace/src/exporters/agent/index.js +0 -1
- package/packages/dd-trace/src/exporters/agent/writer.js +1 -2
- package/packages/dd-trace/src/exporters/agentless/writer.js +3 -3
- package/packages/dd-trace/src/exporters/common/util.js +2 -2
- package/packages/dd-trace/src/id.js +2 -0
- package/packages/dd-trace/src/index.js +2 -5
- package/packages/dd-trace/src/lambda/handler.js +1 -3
- package/packages/dd-trace/src/llmobs/plugins/{anthropic.js → anthropic/index.js} +5 -63
- package/packages/dd-trace/src/llmobs/plugins/anthropic/util.js +106 -0
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chain.js +3 -2
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/chat_model.js +3 -2
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/embedding.js +2 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/index.js +0 -49
- package/packages/dd-trace/src/llmobs/plugins/langchain/handlers/vectorstore.js +2 -1
- package/packages/dd-trace/src/llmobs/plugins/langchain/messages.js +76 -0
- package/packages/dd-trace/src/llmobs/plugins/langgraph/index.js +1 -26
- package/packages/dd-trace/src/llmobs/plugins/modelcontextprotocol-sdk/index.js +68 -0
- package/packages/dd-trace/src/llmobs/plugins/modelcontextprotocol-sdk/utils.js +57 -0
- package/packages/dd-trace/src/llmobs/sdk.js +2 -2
- package/packages/dd-trace/src/log/index.js +0 -10
- package/packages/dd-trace/src/openfeature/eval-metrics-hook.js +103 -0
- package/packages/dd-trace/src/openfeature/flagging_provider.js +3 -0
- package/packages/dd-trace/src/openfeature/remote_config.js +6 -1
- package/packages/dd-trace/src/opentelemetry/context_manager.js +6 -4
- package/packages/dd-trace/src/opentelemetry/logs/index.js +1 -1
- package/packages/dd-trace/src/opentelemetry/logs/otlp_http_log_exporter.js +3 -2
- package/packages/dd-trace/src/opentelemetry/metrics/index.js +1 -1
- package/packages/dd-trace/src/opentelemetry/metrics/otlp_http_metric_exporter.js +3 -2
- package/packages/dd-trace/src/opentelemetry/otlp/otlp_http_exporter_base.js +19 -51
- package/packages/dd-trace/src/opentelemetry/otlp/protobuf_loader.js +14 -2
- package/packages/dd-trace/src/opentelemetry/otlp/trace.proto +358 -0
- package/packages/dd-trace/src/opentelemetry/otlp/trace_service.proto +78 -0
- package/packages/dd-trace/src/opentelemetry/trace/index.js +70 -0
- package/packages/dd-trace/src/opentelemetry/trace/otlp_http_trace_exporter.js +74 -0
- package/packages/dd-trace/src/opentelemetry/trace/otlp_transformer.js +342 -0
- package/packages/dd-trace/src/opentelemetry/tracer.js +9 -11
- package/packages/dd-trace/src/opentracing/propagation/text_map.js +17 -10
- package/packages/dd-trace/src/opentracing/span.js +1 -1
- package/packages/dd-trace/src/opentracing/tracer.js +17 -5
- package/packages/dd-trace/src/plugins/index.js +1 -0
- package/packages/dd-trace/src/plugins/log_plugin.js +3 -0
- package/packages/dd-trace/src/plugins/plugin.js +6 -11
- package/packages/dd-trace/src/plugins/storage.js +2 -2
- package/packages/dd-trace/src/plugins/tracing.js +22 -5
- package/packages/dd-trace/src/plugins/util/test.js +128 -5
- package/packages/dd-trace/src/plugins/util/url.js +2 -1
- package/packages/dd-trace/src/plugins/util/web.js +6 -88
- package/packages/dd-trace/src/profiling/profiler.js +34 -77
- package/packages/dd-trace/src/profiling/profilers/event_plugins/crypto.js +32 -0
- package/packages/dd-trace/src/profiling/profilers/event_plugins/zlib.js +19 -0
- package/packages/dd-trace/src/profiling/profilers/events.js +35 -0
- package/packages/dd-trace/src/proxy.js +3 -4
- package/packages/dd-trace/src/runtime_metrics/runtime_metrics.js +17 -13
- package/packages/dd-trace/src/service-naming/index.js +1 -1
- package/packages/dd-trace/src/service-naming/schemas/definition.js +4 -1
- package/packages/dd-trace/src/service-naming/schemas/util.js +15 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/messaging.js +24 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/storage.js +60 -0
- package/packages/dd-trace/src/service-naming/schemas/v0/web.js +21 -1
- package/packages/dd-trace/src/service-naming/schemas/v0/websocket.js +5 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/storage.js +17 -0
- package/packages/dd-trace/src/service-naming/schemas/v1/web.js +15 -1
- package/packages/dd-trace/src/service-naming/schemas/v1/websocket.js +6 -0
- package/packages/dd-trace/src/span_processor.js +1 -2
- package/packages/dd-trace/src/span_stats.js +5 -1
- package/packages/dd-trace/src/tagger.js +2 -2
- package/packages/dd-trace/src/telemetry/send-data.js +5 -7
- package/vendor/dist/@apm-js-collab/code-transformer/index.js +28 -6
- package/vendor/dist/protobufjs/index.js +1 -1
- package/packages/dd-trace/src/log/utils.js +0 -16
- package/vendor/dist/ignore/LICENSE +0 -21
- package/vendor/dist/ignore/index.js +0 -1
|
@@ -5,7 +5,6 @@ const realDateNow = Date.now.bind(Date)
|
|
|
5
5
|
|
|
6
6
|
const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
|
|
7
7
|
const { storage } = require('../../datadog-core')
|
|
8
|
-
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
|
|
9
8
|
|
|
10
9
|
const {
|
|
11
10
|
TEST_STATUS,
|
|
@@ -406,7 +405,7 @@ class MochaPlugin extends CiPlugin {
|
|
|
406
405
|
finishAllTraceSpans(this.testSessionSpan)
|
|
407
406
|
this.telemetry.count(TELEMETRY_TEST_SESSION, {
|
|
408
407
|
provider: this.ciProviderName,
|
|
409
|
-
autoInjected: !!
|
|
408
|
+
autoInjected: !!this._tracerConfig.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER,
|
|
410
409
|
})
|
|
411
410
|
}
|
|
412
411
|
this.libraryConfig = null
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const CompositePlugin = require('../../dd-trace/src/plugins/composite')
|
|
4
|
+
const mcpLLMObsPlugins = require('../../dd-trace/src/llmobs/plugins/modelcontextprotocol-sdk')
|
|
5
|
+
const tracingPlugins = require('./tracing')
|
|
6
|
+
|
|
7
|
+
const plugins = {}
|
|
8
|
+
|
|
9
|
+
// CRITICAL: LLMObs plugins MUST come first
|
|
10
|
+
for (const Plugin of mcpLLMObsPlugins) {
|
|
11
|
+
plugins[Plugin.id] = Plugin
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Tracing plugins second
|
|
15
|
+
for (const Plugin of tracingPlugins) {
|
|
16
|
+
plugins[Plugin.id] = Plugin
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
class ModelcontextprotocolSdkPlugin extends CompositePlugin {
|
|
20
|
+
static id = 'modelcontextprotocol-sdk'
|
|
21
|
+
static plugins = plugins
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = ModelcontextprotocolSdkPlugin
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const TracingPlugin = require('../../dd-trace/src/plugins/tracing')
|
|
4
|
+
|
|
5
|
+
class McpToolCallPlugin extends TracingPlugin {
|
|
6
|
+
static id = 'modelcontextprotocol_client'
|
|
7
|
+
static prefix = 'tracing:orchestrion:@modelcontextprotocol/sdk:Client_callTool'
|
|
8
|
+
|
|
9
|
+
bindStart (ctx) {
|
|
10
|
+
const params = ctx.arguments?.[0]
|
|
11
|
+
const toolName = params?.name
|
|
12
|
+
|
|
13
|
+
this.startSpan('mcp.client.tool.call', {
|
|
14
|
+
resource: toolName,
|
|
15
|
+
type: 'mcp',
|
|
16
|
+
kind: 'client',
|
|
17
|
+
}, ctx)
|
|
18
|
+
|
|
19
|
+
return ctx.currentStore
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
asyncEnd (ctx) {
|
|
23
|
+
const result = ctx.result
|
|
24
|
+
if (result?.isError) {
|
|
25
|
+
const span = ctx.currentStore?.span
|
|
26
|
+
const errorText = result.content?.find?.(c => c.type === 'text')?.text || 'Tool call returned isError: true'
|
|
27
|
+
span?.setTag('error', new Error(errorText))
|
|
28
|
+
}
|
|
29
|
+
super.finish(ctx)
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
class McpListToolsPlugin extends TracingPlugin {
|
|
34
|
+
static id = 'modelcontextprotocol_list_tools'
|
|
35
|
+
static prefix = 'tracing:orchestrion:@modelcontextprotocol/sdk:Client_listTools'
|
|
36
|
+
|
|
37
|
+
bindStart (ctx) {
|
|
38
|
+
this.startSpan('mcp.tools.list', {
|
|
39
|
+
resource: 'tools/list',
|
|
40
|
+
type: 'mcp',
|
|
41
|
+
kind: 'client',
|
|
42
|
+
}, ctx)
|
|
43
|
+
|
|
44
|
+
return ctx.currentStore
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
asyncEnd (ctx) {
|
|
48
|
+
super.finish(ctx)
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
module.exports = [
|
|
53
|
+
McpToolCallPlugin,
|
|
54
|
+
McpListToolsPlugin,
|
|
55
|
+
]
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { isTrue } = require('../../dd-trace/src/util')
|
|
4
3
|
const DatabasePlugin = require('../../dd-trace/src/plugins/database')
|
|
5
|
-
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
|
|
6
4
|
|
|
7
5
|
class MongodbCorePlugin extends DatabasePlugin {
|
|
8
6
|
static id = 'mongodb-core'
|
|
@@ -20,11 +18,8 @@ class MongodbCorePlugin extends DatabasePlugin {
|
|
|
20
18
|
configure (config) {
|
|
21
19
|
super.configure(config)
|
|
22
20
|
|
|
23
|
-
const heartbeatFromEnv = getValueFromEnvSources('DD_TRACE_MONGODB_HEARTBEAT_ENABLED')
|
|
24
|
-
|
|
25
21
|
this.config.heartbeatEnabled = config.heartbeatEnabled ??
|
|
26
|
-
|
|
27
|
-
true
|
|
22
|
+
this._tracerConfig.DD_TRACE_MONGODB_HEARTBEAT_ENABLED
|
|
28
23
|
}
|
|
29
24
|
|
|
30
25
|
bindStart (ctx) {
|
|
@@ -35,9 +30,9 @@ class MongodbCorePlugin extends DatabasePlugin {
|
|
|
35
30
|
}
|
|
36
31
|
const query = getQuery(ops)
|
|
37
32
|
const resource = truncate(getResource(this, ns, query, name))
|
|
38
|
-
const
|
|
33
|
+
const serviceResult = this.serviceName({ pluginConfig: this.config })
|
|
39
34
|
const span = this.startSpan(this.operationName(), {
|
|
40
|
-
service,
|
|
35
|
+
service: serviceResult,
|
|
41
36
|
resource,
|
|
42
37
|
type: 'mongodb',
|
|
43
38
|
kind: 'client',
|
|
@@ -49,7 +44,7 @@ class MongodbCorePlugin extends DatabasePlugin {
|
|
|
49
44
|
'out.port': options.port,
|
|
50
45
|
},
|
|
51
46
|
}, ctx)
|
|
52
|
-
const comment = this.injectDbmComment(span, ops.comment,
|
|
47
|
+
const comment = this.injectDbmComment(span, ops.comment, serviceResult.name)
|
|
53
48
|
if (comment) {
|
|
54
49
|
ops.comment = comment
|
|
55
50
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
const ServerPlugin = require('../../dd-trace/src/plugins/server')
|
|
4
4
|
const { storage } = require('../../datadog-core')
|
|
5
5
|
const analyticsSampler = require('../../dd-trace/src/analytics_sampler')
|
|
6
|
-
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
6
|
+
const { COMPONENT, SVC_SRC_KEY } = require('../../dd-trace/src/constants')
|
|
7
7
|
const web = require('../../dd-trace/src/plugins/util/web')
|
|
8
8
|
|
|
9
9
|
const errorPages = new Set(['/404', '/500', '/_error', '/_not-found', '/_not-found/page'])
|
|
@@ -19,15 +19,21 @@ class NextPlugin extends ServerPlugin {
|
|
|
19
19
|
bindStart ({ req, res }) {
|
|
20
20
|
const store = storage('legacy').getStore()
|
|
21
21
|
const childOf = store ? store.span : store
|
|
22
|
+
const { name: schemaServiceName, source: schemaServiceSource } = this.serviceName()
|
|
23
|
+
const serviceName = this.config.service || schemaServiceName
|
|
24
|
+
let serviceSource = this.config.service ? 'opt.plugin' : schemaServiceSource
|
|
25
|
+
if (!serviceName || serviceName === this.tracer._service) serviceSource = undefined
|
|
26
|
+
|
|
22
27
|
const span = this.tracer.startSpan(this.operationName(), {
|
|
23
28
|
childOf,
|
|
24
29
|
tags: {
|
|
25
30
|
[COMPONENT]: this.constructor.id,
|
|
26
|
-
'service.name':
|
|
31
|
+
'service.name': serviceName,
|
|
27
32
|
'resource.name': req.method,
|
|
28
33
|
'span.type': 'web',
|
|
29
34
|
'span.kind': 'server',
|
|
30
35
|
'http.method': req.method,
|
|
36
|
+
...(serviceSource === undefined ? {} : { [SVC_SRC_KEY]: serviceSource }),
|
|
31
37
|
},
|
|
32
38
|
integrationName: this.constructor.id,
|
|
33
39
|
})
|
|
@@ -32,7 +32,7 @@ class PGPlugin extends DatabasePlugin {
|
|
|
32
32
|
span.setTag('db.stream', 1)
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
query.__ddInjectableQuery = this.injectDbmQuery(span, query.text, service, !!query.name)
|
|
35
|
+
query.__ddInjectableQuery = this.injectDbmQuery(span, query.text, service.name, !!query.name)
|
|
36
36
|
|
|
37
37
|
return ctx.currentStore
|
|
38
38
|
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
const { storage } = require('../../datadog-core')
|
|
4
4
|
const id = require('../../dd-trace/src/id')
|
|
5
5
|
const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
|
|
6
|
-
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
|
|
7
6
|
|
|
8
7
|
const {
|
|
9
8
|
finishAllTraceSpans,
|
|
@@ -108,7 +107,7 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
108
107
|
finishAllTraceSpans(this.testSessionSpan)
|
|
109
108
|
this.telemetry.count(TELEMETRY_TEST_SESSION, {
|
|
110
109
|
provider: this.ciProviderName,
|
|
111
|
-
autoInjected: !!
|
|
110
|
+
autoInjected: !!this._tracerConfig.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER,
|
|
112
111
|
})
|
|
113
112
|
appClosingTelemetry()
|
|
114
113
|
this.tracer._exporter.flush(onDone)
|
|
@@ -420,7 +419,7 @@ class PlaywrightPlugin extends CiPlugin {
|
|
|
420
419
|
span.finish()
|
|
421
420
|
|
|
422
421
|
finishAllTraceSpans(span)
|
|
423
|
-
if (
|
|
422
|
+
if (this._tracerConfig.DD_PLAYWRIGHT_WORKER) {
|
|
424
423
|
this.tracer._exporter.flush(onDone)
|
|
425
424
|
}
|
|
426
425
|
})
|
|
@@ -28,7 +28,7 @@ class TediousPlugin extends DatabasePlugin {
|
|
|
28
28
|
|
|
29
29
|
// SQL Server includes comments when caching queries
|
|
30
30
|
// For that reason we allow service mode but not full mode
|
|
31
|
-
ctx.sql = this.injectDbmQuery(span, ctx.queryOrProcedure, service, true)
|
|
31
|
+
ctx.sql = this.injectDbmQuery(span, ctx.queryOrProcedure, service.name, true)
|
|
32
32
|
return ctx.currentStore
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const CiPlugin = require('../../dd-trace/src/plugins/ci_plugin')
|
|
4
4
|
const { storage } = require('../../datadog-core')
|
|
5
|
-
const { getValueFromEnvSources } = require('../../dd-trace/src/config/helper')
|
|
6
5
|
|
|
7
6
|
const {
|
|
8
7
|
TEST_STATUS,
|
|
@@ -34,6 +33,7 @@ const {
|
|
|
34
33
|
isModifiedTest,
|
|
35
34
|
TEST_IS_MODIFIED,
|
|
36
35
|
TEST_HAS_DYNAMIC_NAME,
|
|
36
|
+
TEST_FINAL_STATUS,
|
|
37
37
|
} = require('../../dd-trace/src/plugins/util/test')
|
|
38
38
|
const { COMPONENT } = require('../../dd-trace/src/constants')
|
|
39
39
|
const {
|
|
@@ -213,10 +213,13 @@ class VitestPlugin extends CiPlugin {
|
|
|
213
213
|
return ctx.currentStore
|
|
214
214
|
})
|
|
215
215
|
|
|
216
|
-
this.addSub('ci:vitest:test:pass', ({ span, task }) => {
|
|
216
|
+
this.addSub('ci:vitest:test:pass', ({ span, task, finalStatus }) => {
|
|
217
217
|
if (span) {
|
|
218
218
|
this.telemetry.ciVisEvent(TELEMETRY_EVENT_FINISHED, 'test', this.getTestTelemetryTags(span))
|
|
219
219
|
span.setTag(TEST_STATUS, 'pass')
|
|
220
|
+
if (finalStatus) {
|
|
221
|
+
span.setTag(TEST_FINAL_STATUS, finalStatus)
|
|
222
|
+
}
|
|
220
223
|
span.finish(this.taskToFinishTime.get(task))
|
|
221
224
|
finishAllTraceSpans(span)
|
|
222
225
|
}
|
|
@@ -230,6 +233,7 @@ class VitestPlugin extends CiPlugin {
|
|
|
230
233
|
promises,
|
|
231
234
|
hasFailedAllRetries,
|
|
232
235
|
attemptToFixFailed,
|
|
236
|
+
finalStatus,
|
|
233
237
|
}) => {
|
|
234
238
|
if (!span) {
|
|
235
239
|
return
|
|
@@ -255,6 +259,9 @@ class VitestPlugin extends CiPlugin {
|
|
|
255
259
|
if (attemptToFixFailed) {
|
|
256
260
|
span.setTag(TEST_MANAGEMENT_ATTEMPT_TO_FIX_PASSED, 'false')
|
|
257
261
|
}
|
|
262
|
+
if (finalStatus) {
|
|
263
|
+
span.setTag(TEST_FINAL_STATUS, finalStatus)
|
|
264
|
+
}
|
|
258
265
|
if (duration) {
|
|
259
266
|
span.finish(span._startTime + duration - MILLISECONDS_TO_SUBTRACT_FROM_FAILED_TEST_DURATION) // milliseconds
|
|
260
267
|
} else {
|
|
@@ -273,6 +280,7 @@ class VitestPlugin extends CiPlugin {
|
|
|
273
280
|
[TEST_SOURCE_FILE]: testSuite,
|
|
274
281
|
[TEST_SOURCE_START]: 1, // we can't get the proper start line in vitest
|
|
275
282
|
[TEST_STATUS]: 'skip',
|
|
283
|
+
[TEST_FINAL_STATUS]: 'skip',
|
|
276
284
|
...(isDisabled ? { [TEST_MANAGEMENT_IS_DISABLED]: 'true' } : {}),
|
|
277
285
|
...(isNew ? { [TEST_IS_NEW]: 'true' } : {}),
|
|
278
286
|
}
|
|
@@ -285,12 +293,12 @@ class VitestPlugin extends CiPlugin {
|
|
|
285
293
|
const { testSuiteAbsolutePath, frameworkVersion } = ctx
|
|
286
294
|
|
|
287
295
|
// TODO: Handle case where the command is not set
|
|
288
|
-
this.command =
|
|
296
|
+
this.command = this._tracerConfig.DD_CIVISIBILITY_TEST_COMMAND
|
|
289
297
|
this.frameworkVersion = frameworkVersion
|
|
290
298
|
const testSessionSpanContext = this.tracer.extract('text_map', {
|
|
291
299
|
// TODO: Handle case where the session ID or module ID is not set
|
|
292
|
-
'x-datadog-trace-id':
|
|
293
|
-
'x-datadog-parent-id':
|
|
300
|
+
'x-datadog-trace-id': this._tracerConfig.DD_CIVISIBILITY_TEST_SESSION_ID,
|
|
301
|
+
'x-datadog-parent-id': this._tracerConfig.DD_CIVISIBILITY_TEST_MODULE_ID,
|
|
294
302
|
})
|
|
295
303
|
|
|
296
304
|
const trimmedCommand = DD_MAJOR < 6 ? this.command : 'vitest run'
|
|
@@ -415,7 +423,7 @@ class VitestPlugin extends CiPlugin {
|
|
|
415
423
|
finishAllTraceSpans(this.testSessionSpan)
|
|
416
424
|
this.telemetry.count(TELEMETRY_TEST_SESSION, {
|
|
417
425
|
provider: this.ciProviderName,
|
|
418
|
-
autoInjected: !!
|
|
426
|
+
autoInjected: !!this._tracerConfig.DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER,
|
|
419
427
|
})
|
|
420
428
|
this.tracer._exporter.flush(onFinish)
|
|
421
429
|
})
|
|
@@ -47,7 +47,7 @@ class WSClosePlugin extends TracingPlugin {
|
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
if (isPeerClose && traceWebsocketMessagesInheritSampling && traceWebsocketMessagesSeparateTraces) {
|
|
50
|
-
span.setTag('_dd.dm.service', spanTags['service.name'] || service)
|
|
50
|
+
span.setTag('_dd.dm.service', spanTags['service.name'] || service.name)
|
|
51
51
|
span.setTag('_dd.dm.resource', spanTags['resource.name'] || `websocket ${path}`)
|
|
52
52
|
span.setTag('_dd.dm.inherited', 1)
|
|
53
53
|
}
|
|
@@ -57,11 +57,13 @@ class WSClosePlugin extends TracingPlugin {
|
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
bindAsyncStart (ctx) {
|
|
60
|
+
if (!ctx.span) return ctx.parentStore
|
|
60
61
|
if (!ctx.isPeerClose) ctx.span.finish()
|
|
61
62
|
return ctx.parentStore
|
|
62
63
|
}
|
|
63
64
|
|
|
64
65
|
asyncStart (ctx) {
|
|
66
|
+
if (!ctx.span) return
|
|
65
67
|
ctx.span.finish()
|
|
66
68
|
}
|
|
67
69
|
|
|
@@ -46,11 +46,13 @@ class WSProducerPlugin extends TracingPlugin {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
bindAsyncStart (ctx) {
|
|
49
|
+
if (!ctx.span) return ctx.parentStore
|
|
49
50
|
ctx.span.finish()
|
|
50
51
|
return ctx.parentStore
|
|
51
52
|
}
|
|
52
53
|
|
|
53
54
|
asyncStart (ctx) {
|
|
55
|
+
if (!ctx.span) return
|
|
54
56
|
ctx.span.finish()
|
|
55
57
|
}
|
|
56
58
|
|
|
@@ -48,7 +48,7 @@ class WSReceiverPlugin extends TracingPlugin {
|
|
|
48
48
|
}, ctx)
|
|
49
49
|
|
|
50
50
|
if (traceWebsocketMessagesInheritSampling && traceWebsocketMessagesSeparateTraces) {
|
|
51
|
-
span.setTag('_dd.dm.service', spanTags['service.name'] || service)
|
|
51
|
+
span.setTag('_dd.dm.service', spanTags['service.name'] || service.name)
|
|
52
52
|
span.setTag('_dd.dm.resource', spanTags['resource.name'] || `websocket ${path}`)
|
|
53
53
|
span.setTag('_dd.dm.inherited', 1)
|
|
54
54
|
}
|
|
@@ -62,6 +62,7 @@ class WSReceiverPlugin extends TracingPlugin {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
asyncStart (ctx) {
|
|
65
|
+
if (!ctx.span) return
|
|
65
66
|
ctx.span.finish()
|
|
66
67
|
}
|
|
67
68
|
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const { channel } = require('dc-polyfill')
|
|
4
3
|
const log = require('../log')
|
|
4
|
+
const { incomingHttpRequestStart, aiguardChannel } = require('./channels')
|
|
5
5
|
const AIGuard = require('./sdk')
|
|
6
6
|
|
|
7
|
-
const aiguardChannel = channel('dd-trace:ai:aiguard')
|
|
8
|
-
|
|
9
7
|
let isEnabled = false
|
|
10
8
|
let aiguard
|
|
11
9
|
let block
|
|
12
10
|
|
|
11
|
+
function onIncomingHttpRequestStart () {
|
|
12
|
+
// No-op: subscribing ensures the HTTP plugin spreads req onto the store
|
|
13
|
+
}
|
|
14
|
+
|
|
13
15
|
function enable (tracer, config) {
|
|
14
16
|
if (isEnabled) return
|
|
15
17
|
|
|
@@ -17,6 +19,7 @@ function enable (tracer, config) {
|
|
|
17
19
|
aiguard = new AIGuard(tracer, config)
|
|
18
20
|
block = config.experimental?.aiguard?.block !== false
|
|
19
21
|
|
|
22
|
+
incomingHttpRequestStart.subscribe(onIncomingHttpRequestStart)
|
|
20
23
|
aiguardChannel.subscribe(onEvaluate)
|
|
21
24
|
|
|
22
25
|
isEnabled = true
|
|
@@ -29,6 +32,7 @@ function enable (tracer, config) {
|
|
|
29
32
|
function disable () {
|
|
30
33
|
if (!isEnabled) return
|
|
31
34
|
|
|
35
|
+
incomingHttpRequestStart.unsubscribe(onIncomingHttpRequestStart)
|
|
32
36
|
aiguardChannel.unsubscribe(onEvaluate)
|
|
33
37
|
|
|
34
38
|
aiguard = undefined
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const rfdc = require('../../../../vendor/dist/rfdc')({ proto: false, circles: false })
|
|
4
|
+
const { HTTP_CLIENT_IP, NETWORK_CLIENT_IP } = require('../../../../ext/tags')
|
|
5
|
+
const { getActiveRequest } = require('../appsec/store')
|
|
4
6
|
const log = require('../log')
|
|
7
|
+
const { extractIp } = require('../plugins/util/ip_extractor')
|
|
5
8
|
const telemetryMetrics = require('../telemetry/metrics')
|
|
6
9
|
const tracerVersion = require('../../../../package.json').version
|
|
7
10
|
const { keepTrace } = require('../priority_sampler')
|
|
@@ -13,6 +16,7 @@ const {
|
|
|
13
16
|
AI_GUARD_TARGET_TAG_KEY,
|
|
14
17
|
AI_GUARD_REASON_TAG_KEY,
|
|
15
18
|
AI_GUARD_ACTION_TAG_KEY,
|
|
19
|
+
AI_GUARD_EVENT_TAG_KEY,
|
|
16
20
|
AI_GUARD_BLOCKED_TAG_KEY,
|
|
17
21
|
AI_GUARD_META_STRUCT_KEY,
|
|
18
22
|
AI_GUARD_TOOL_NAME_TAG_KEY,
|
|
@@ -25,11 +29,12 @@ const appsecMetrics = telemetryMetrics.manager.namespace('appsec')
|
|
|
25
29
|
const ALLOW = 'ALLOW'
|
|
26
30
|
|
|
27
31
|
class AIGuardAbortError extends Error {
|
|
28
|
-
constructor (reason, tags, sds) {
|
|
32
|
+
constructor (reason, tags, tagProbs, sds) {
|
|
29
33
|
super(reason)
|
|
30
34
|
this.name = 'AIGuardAbortError'
|
|
31
35
|
this.reason = reason
|
|
32
36
|
this.tags = tags
|
|
37
|
+
this.tagProbabilities = tagProbs
|
|
33
38
|
this.sds = sds || []
|
|
34
39
|
}
|
|
35
40
|
}
|
|
@@ -56,6 +61,7 @@ class AIGuard extends NoopAIGuard {
|
|
|
56
61
|
#maxMessagesLength
|
|
57
62
|
#maxContentSize
|
|
58
63
|
#meta
|
|
64
|
+
#config
|
|
59
65
|
|
|
60
66
|
/**
|
|
61
67
|
* @param {import('../tracer')} tracer - Tracer instance
|
|
@@ -83,6 +89,7 @@ class AIGuard extends NoopAIGuard {
|
|
|
83
89
|
this.#maxMessagesLength = config.experimental.aiguard.maxMessagesLength
|
|
84
90
|
this.#maxContentSize = config.experimental.aiguard.maxContentSize
|
|
85
91
|
this.#meta = { service: config.service, env: config.env }
|
|
92
|
+
this.#config = config
|
|
86
93
|
this.#initialized = true
|
|
87
94
|
}
|
|
88
95
|
|
|
@@ -138,6 +145,42 @@ class AIGuard extends NoopAIGuard {
|
|
|
138
145
|
return null
|
|
139
146
|
}
|
|
140
147
|
|
|
148
|
+
#setRootSpanClientIpTags (rootSpan) {
|
|
149
|
+
if (!rootSpan) return
|
|
150
|
+
|
|
151
|
+
const currentTags = rootSpan.context()._tags
|
|
152
|
+
const needsHttpClientIp = !Object.hasOwn(currentTags, HTTP_CLIENT_IP)
|
|
153
|
+
const needsNetworkClientIp = !Object.hasOwn(currentTags, NETWORK_CLIENT_IP)
|
|
154
|
+
|
|
155
|
+
if (!needsHttpClientIp && !needsNetworkClientIp) return
|
|
156
|
+
|
|
157
|
+
const req = getActiveRequest()
|
|
158
|
+
|
|
159
|
+
if (!req) return
|
|
160
|
+
|
|
161
|
+
const newTags = {}
|
|
162
|
+
|
|
163
|
+
if (needsHttpClientIp) {
|
|
164
|
+
const clientIp = extractIp(this.#config, req)
|
|
165
|
+
|
|
166
|
+
if (clientIp) {
|
|
167
|
+
newTags[HTTP_CLIENT_IP] = clientIp
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (needsNetworkClientIp) {
|
|
172
|
+
const networkClientIp = req.socket?.remoteAddress
|
|
173
|
+
|
|
174
|
+
if (networkClientIp) {
|
|
175
|
+
newTags[NETWORK_CLIENT_IP] = networkClientIp
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (Object.keys(newTags).length > 0) {
|
|
180
|
+
rootSpan.addTags(newTags)
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
141
184
|
evaluate (messages, opts) {
|
|
142
185
|
if (!this.#initialized) {
|
|
143
186
|
return super.evaluate(messages, opts)
|
|
@@ -161,9 +204,11 @@ class AIGuard extends NoopAIGuard {
|
|
|
161
204
|
}
|
|
162
205
|
const rootSpan = span.context()?._trace?.started?.[0]
|
|
163
206
|
if (rootSpan) {
|
|
207
|
+
this.#setRootSpanClientIpTags(rootSpan)
|
|
164
208
|
// keepTrace must be called before executeRequest so the sampling decision
|
|
165
209
|
// is propagated correctly to outgoing HTTP client calls.
|
|
166
210
|
keepTrace(rootSpan, AI_GUARD)
|
|
211
|
+
rootSpan.setTag(AI_GUARD_EVENT_TAG_KEY, 'true')
|
|
167
212
|
}
|
|
168
213
|
let response
|
|
169
214
|
try {
|
|
@@ -188,38 +233,37 @@ class AIGuard extends NoopAIGuard {
|
|
|
188
233
|
`AI Guard service call failed, status ${response.status}`,
|
|
189
234
|
{ errors: response.body?.errors })
|
|
190
235
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
const attr = response.body.data.attributes
|
|
194
|
-
if (!attr.action) {
|
|
195
|
-
throw new Error('Action missing from response')
|
|
196
|
-
}
|
|
197
|
-
action = attr.action
|
|
198
|
-
reason = attr.reason
|
|
199
|
-
tags = attr.tags
|
|
200
|
-
sdsFindings = attr.sds_findings || []
|
|
201
|
-
blockingEnabled = attr.is_blocking_enabled ?? false
|
|
202
|
-
} catch (e) {
|
|
236
|
+
const attr = response.body?.data?.attributes
|
|
237
|
+
if (!attr?.action) {
|
|
203
238
|
appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { error: true }).inc(1)
|
|
204
|
-
throw new AIGuardClientError(`AI Guard service returned unexpected response : ${response.body}
|
|
239
|
+
throw new AIGuardClientError(`AI Guard service returned unexpected response : ${response.body}`)
|
|
240
|
+
}
|
|
241
|
+
const action = attr.action
|
|
242
|
+
const reason = attr.reason
|
|
243
|
+
const tags = attr.tags ?? []
|
|
244
|
+
if (tags.length > 0) {
|
|
245
|
+
metaStruct.attack_categories = tags
|
|
205
246
|
}
|
|
247
|
+
const sdsFindings = attr.sds_findings ?? []
|
|
248
|
+
if (sdsFindings.length > 0) {
|
|
249
|
+
metaStruct.sds = sdsFindings
|
|
250
|
+
}
|
|
251
|
+
const tagProbabilities = attr.tag_probs ?? {}
|
|
252
|
+
if (attr.tag_probs) {
|
|
253
|
+
metaStruct.tag_probs = tagProbabilities
|
|
254
|
+
}
|
|
255
|
+
const blockingEnabled = attr.is_blocking_enabled ?? false
|
|
206
256
|
const shouldBlock = block && blockingEnabled && action !== ALLOW
|
|
207
257
|
appsecMetrics.count(AI_GUARD_TELEMETRY_REQUESTS, { action, error: false, block: shouldBlock }).inc(1)
|
|
208
258
|
span.setTag(AI_GUARD_ACTION_TAG_KEY, action)
|
|
209
259
|
if (reason) {
|
|
210
260
|
span.setTag(AI_GUARD_REASON_TAG_KEY, reason)
|
|
211
261
|
}
|
|
212
|
-
if (tags?.length > 0) {
|
|
213
|
-
metaStruct.attack_categories = tags
|
|
214
|
-
}
|
|
215
|
-
if (sdsFindings?.length > 0) {
|
|
216
|
-
metaStruct.sds = sdsFindings
|
|
217
|
-
}
|
|
218
262
|
if (shouldBlock) {
|
|
219
263
|
span.setTag(AI_GUARD_BLOCKED_TAG_KEY, 'true')
|
|
220
|
-
throw new AIGuardAbortError(reason, tags, sdsFindings)
|
|
264
|
+
throw new AIGuardAbortError(reason, tags, tagProbabilities, sdsFindings)
|
|
221
265
|
}
|
|
222
|
-
return { action, reason, tags, sds: sdsFindings }
|
|
266
|
+
return { action, reason, tags, tagProbabilities, sds: sdsFindings }
|
|
223
267
|
})
|
|
224
268
|
}
|
|
225
269
|
}
|
|
@@ -7,6 +7,7 @@ module.exports = {
|
|
|
7
7
|
AI_GUARD_ACTION_TAG_KEY: 'ai_guard.action',
|
|
8
8
|
AI_GUARD_REASON_TAG_KEY: 'ai_guard.reason',
|
|
9
9
|
AI_GUARD_BLOCKED_TAG_KEY: 'ai_guard.blocked',
|
|
10
|
+
AI_GUARD_EVENT_TAG_KEY: 'ai_guard.event',
|
|
10
11
|
AI_GUARD_META_STRUCT_KEY: 'ai_guard',
|
|
11
12
|
|
|
12
13
|
AI_GUARD_TELEMETRY_REQUESTS: 'ai_guard.requests',
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/* eslint-disable @stylistic/max-len */
|
|
2
|
+
/* eslint-disable @stylistic/quotes */
|
|
2
3
|
'use strict'
|
|
3
4
|
|
|
4
|
-
const html =
|
|
5
|
+
const html = `<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>You've been blocked</title><style>a,body,div,html,span{margin:0;padding:0;border:0;font-size:100%;font:inherit;vertical-align:baseline}body{background:-webkit-radial-gradient(26% 19%,circle,#fff,#f4f7f9);background:radial-gradient(circle at 26% 19%,#fff,#f4f7f9);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:center;align-content:center;width:100%;min-height:100vh;line-height:1;flex-direction:column}p{display:block}main{text-align:center;flex:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-line-pack:center;align-content:center;flex-direction:column}p{font-size:18px;line-height:normal;color:#646464;font-family:sans-serif;font-weight:400}a{color:#4842b7}footer{width:100%;text-align:center}footer p{font-size:16px}.security-response-id{font-size:14px;color:#999;margin-top:20px;font-family:monospace}</style></head><body><main><p>Sorry, you cannot access this page. Please contact the customer service team.</p><p class="security-response-id">Security Response ID: [security_response_id]</p></main><footer><p>Security provided by <a href="https://www.datadoghq.com/product/security-platform/application-security-monitoring/" target="_blank" rel="noopener noreferrer">Datadog</a></p></footer></body></html>`
|
|
5
6
|
|
|
6
|
-
const json =
|
|
7
|
+
const json = `{"errors":[{"title":"You've been blocked","detail":"Sorry, you cannot access this page. Please contact the customer service team. Security provided by Datadog."}],"security_response_id":"[security_response_id]"}`
|
|
7
8
|
|
|
8
|
-
const graphqlJson =
|
|
9
|
+
const graphqlJson = `{"errors":[{"message":"You've been blocked","extensions":{"detail":"Sorry, you cannot perform this operation. Please contact the customer service team. Security provided by Datadog."}}],"security_response_id":"[security_response_id]"}`
|
|
9
10
|
|
|
10
11
|
module.exports = {
|
|
11
12
|
html,
|