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
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Formats tool call input as a JSON string.
|
|
5
|
+
* @param {string} toolName - The name of the tool being called
|
|
6
|
+
* @param {object} toolArguments - The arguments passed to the tool
|
|
7
|
+
* @returns {string} Formatted input string
|
|
8
|
+
*/
|
|
9
|
+
function formatInput (toolName, toolArguments) {
|
|
10
|
+
if (!toolName && !toolArguments) return ''
|
|
11
|
+
|
|
12
|
+
if (toolArguments === undefined || toolArguments === null) {
|
|
13
|
+
return toolName || ''
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
return JSON.stringify({ name: toolName, arguments: toolArguments })
|
|
18
|
+
} catch {
|
|
19
|
+
return toolName || ''
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Formats MCP tool call result as a structured object matching Python's output format.
|
|
25
|
+
* MCP tool results contain a `content` array with items like:
|
|
26
|
+
* `[{ type: 'text', text: '...' }, { type: 'image', data: '...', mimeType: '...' }]`
|
|
27
|
+
* @param {object} result - The MCP CallToolResult
|
|
28
|
+
* @returns {string} JSON string of `{ content: Array<{type, text, annotations, meta}>, isError: boolean }`
|
|
29
|
+
*/
|
|
30
|
+
function formatOutput (result) {
|
|
31
|
+
if (!result) return ''
|
|
32
|
+
|
|
33
|
+
const content = result.content
|
|
34
|
+
const isError = result.isError || false
|
|
35
|
+
|
|
36
|
+
const processed = []
|
|
37
|
+
if (Array.isArray(content)) {
|
|
38
|
+
for (const item of content) {
|
|
39
|
+
if (item.type !== 'text') continue
|
|
40
|
+
const contentBlock = {
|
|
41
|
+
type: item.type,
|
|
42
|
+
text: item.text || '',
|
|
43
|
+
annotations: item.annotations || {},
|
|
44
|
+
meta: item._meta || {},
|
|
45
|
+
}
|
|
46
|
+
processed.push(contentBlock)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
return JSON.stringify({ content: processed, isError })
|
|
52
|
+
} catch {
|
|
53
|
+
return ''
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
module.exports = { formatInput, formatOutput }
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { channel } = require('dc-polyfill')
|
|
4
4
|
|
|
5
|
-
const {
|
|
5
|
+
const { isError, isTrue } = require('../util')
|
|
6
6
|
const tracerVersion = require('../../../../package.json').version
|
|
7
7
|
const logger = require('../log')
|
|
8
8
|
const { getValueFromEnvSources } = require('../config/helper')
|
|
@@ -427,7 +427,7 @@ class LLMObs extends NoopLLMObs {
|
|
|
427
427
|
}
|
|
428
428
|
|
|
429
429
|
// When OTel tracing is enabled, add source:otel tag to allow backend to wait for OTel span conversion
|
|
430
|
-
if (
|
|
430
|
+
if (this._config.DD_TRACE_OTEL_ENABLED) {
|
|
431
431
|
evaluationTags.source = 'otel'
|
|
432
432
|
}
|
|
433
433
|
|
|
@@ -8,7 +8,6 @@ const { getValueFromEnvSources } = require('../config/helper')
|
|
|
8
8
|
const { traceChannel, debugChannel, infoChannel, warnChannel, errorChannel } = require('./channels')
|
|
9
9
|
const logWriter = require('./writer')
|
|
10
10
|
const { Log, LogConfig, NoTransmitError } = require('./log')
|
|
11
|
-
const { memoize } = require('./utils')
|
|
12
11
|
|
|
13
12
|
const config = {
|
|
14
13
|
enabled: defaults.DD_TRACE_DEBUG,
|
|
@@ -16,11 +15,6 @@ const config = {
|
|
|
16
15
|
logLevel: defaults.logLevel,
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
const deprecate = memoize((code, message) => {
|
|
20
|
-
publishFormatted(errorChannel, null, message)
|
|
21
|
-
return true
|
|
22
|
-
})
|
|
23
|
-
|
|
24
18
|
// In most places where we know we want to mute a log we use log.error() directly
|
|
25
19
|
const NO_TRANSMIT = new LogConfig(false)
|
|
26
20
|
|
|
@@ -82,10 +76,6 @@ const log = {
|
|
|
82
76
|
return log
|
|
83
77
|
},
|
|
84
78
|
|
|
85
|
-
deprecate (code, message) {
|
|
86
|
-
return deprecate(code, message)
|
|
87
|
-
},
|
|
88
|
-
|
|
89
79
|
configure (options) {
|
|
90
80
|
config.logger = options.logger
|
|
91
81
|
config.logLevel = options.logLevel ??
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const log = require('../log')
|
|
4
|
+
|
|
5
|
+
const METER_NAME = 'dd-trace-js/openfeature'
|
|
6
|
+
const COUNTER_NAME = 'feature_flag.evaluations'
|
|
7
|
+
const COUNTER_DESCRIPTION = 'Number of feature flag evaluations'
|
|
8
|
+
const COUNTER_UNIT = '{evaluation}'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* OpenFeature hook that tracks feature flag evaluation metrics using an
|
|
12
|
+
* OpenTelemetry counter.
|
|
13
|
+
*
|
|
14
|
+
* Implements the OpenFeature `finally` hook interface so it can be pushed
|
|
15
|
+
* directly onto a provider's `hooks` array. We use the `finally` stage
|
|
16
|
+
* (not diagnostic channels inside the provider's `resolve*` methods) because
|
|
17
|
+
* the OpenFeature SDK short-circuits before calling the provider when it is in
|
|
18
|
+
* NOT_READY state; the `finally` hook still fires, ensuring all evaluations are
|
|
19
|
+
* captured. It also catches type-mismatch errors detected by the SDK client
|
|
20
|
+
* after the provider returns.
|
|
21
|
+
*
|
|
22
|
+
* The counter is created lazily on the first successful `finally()` call rather
|
|
23
|
+
* than in the constructor. This is necessary because `FlaggingProvider` is
|
|
24
|
+
* constructed eagerly by `proxy.js#updateTracing()`, which runs *before*
|
|
25
|
+
* `initializeOpenTelemetryMetrics()` sets the global OTel meter provider.
|
|
26
|
+
* Calling `getMeter()` in the constructor would return the noop meter and
|
|
27
|
+
* produce a noop counter that silently discards all measurements. By deferring
|
|
28
|
+
* to `finally()` time we give the meter provider a chance to be set up first.
|
|
29
|
+
*
|
|
30
|
+
* If counter creation fails (e.g. the OTel API is not yet available), the call
|
|
31
|
+
* is silently skipped and retried on the next `finally()` invocation.
|
|
32
|
+
*
|
|
33
|
+
* When `config.otelMetricsEnabled` is false, `finally()` is always a no-op.
|
|
34
|
+
*/
|
|
35
|
+
class EvalMetricsHook {
|
|
36
|
+
#enabled = false
|
|
37
|
+
#counter = null
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* @param {import('../config')} config - Tracer configuration object
|
|
41
|
+
*/
|
|
42
|
+
constructor (config) {
|
|
43
|
+
this.#enabled = config.otelMetricsEnabled === true
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Returns the OTel counter, creating it on first successful call.
|
|
48
|
+
* Returns `null` if counter creation fails; will retry on next call.
|
|
49
|
+
*
|
|
50
|
+
* @returns {import('@opentelemetry/api').Counter | null}
|
|
51
|
+
*/
|
|
52
|
+
#getCounter () {
|
|
53
|
+
if (this.#counter) return this.#counter
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
const { metrics } = require('@opentelemetry/api')
|
|
57
|
+
const meter = metrics.getMeter(METER_NAME)
|
|
58
|
+
this.#counter = meter.createCounter(COUNTER_NAME, {
|
|
59
|
+
description: COUNTER_DESCRIPTION,
|
|
60
|
+
unit: COUNTER_UNIT,
|
|
61
|
+
})
|
|
62
|
+
} catch (e) {
|
|
63
|
+
log.warn('EvalMetricsHook: failed to create counter: %s', e.message)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return this.#counter
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Called by the OpenFeature SDK after every flag evaluation (success or error).
|
|
71
|
+
*
|
|
72
|
+
* @param {{ flagKey: string }} hookContext - Hook context containing the flag key
|
|
73
|
+
* @param {{ variant?: string, reason?: string, errorCode?: string, flagMetadata?: object }} evaluationDetails
|
|
74
|
+
* - Full evaluation details
|
|
75
|
+
* @returns {void}
|
|
76
|
+
*/
|
|
77
|
+
finally (hookContext, evaluationDetails) {
|
|
78
|
+
if (!this.#enabled) return
|
|
79
|
+
|
|
80
|
+
const counter = this.#getCounter()
|
|
81
|
+
if (!counter) return
|
|
82
|
+
|
|
83
|
+
const attributes = {
|
|
84
|
+
'feature_flag.key': hookContext?.flagKey ?? '',
|
|
85
|
+
'feature_flag.result.variant': evaluationDetails?.variant ?? '',
|
|
86
|
+
'feature_flag.result.reason': evaluationDetails?.reason?.toLowerCase() ?? 'unknown',
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const errorCode = evaluationDetails?.errorCode
|
|
90
|
+
if (errorCode) {
|
|
91
|
+
attributes['error.type'] = errorCode.toLowerCase()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const allocationKey = evaluationDetails?.flagMetadata?.allocationKey
|
|
95
|
+
if (allocationKey) {
|
|
96
|
+
attributes['feature_flag.result.allocation_key'] = allocationKey
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
counter.add(1, attributes)
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
module.exports = EvalMetricsHook
|
|
@@ -4,6 +4,7 @@ const { DatadogNodeServerProvider } = require('@datadog/openfeature-node-server'
|
|
|
4
4
|
const { channel } = require('dc-polyfill')
|
|
5
5
|
const log = require('../log')
|
|
6
6
|
const { EXPOSURE_CHANNEL } = require('./constants/constants')
|
|
7
|
+
const EvalMetricsHook = require('./eval-metrics-hook')
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* OpenFeature provider that integrates with Datadog's feature flagging system.
|
|
@@ -24,6 +25,8 @@ class FlaggingProvider extends DatadogNodeServerProvider {
|
|
|
24
25
|
this._tracer = tracer
|
|
25
26
|
this._config = config
|
|
26
27
|
|
|
28
|
+
this.hooks.push(new EvalMetricsHook(config))
|
|
29
|
+
|
|
27
30
|
log.debug('%s created with timeout: %dms', this.constructor.name,
|
|
28
31
|
config.experimental.flaggingProvider.initializationTimeoutMs)
|
|
29
32
|
}
|
|
@@ -19,9 +19,14 @@ function enable (rc, config, getOpenfeatureProxy) {
|
|
|
19
19
|
|
|
20
20
|
// Set product handler for FFE_FLAGS
|
|
21
21
|
rc.setProductHandler('FFE_FLAGS', (action, conf) => {
|
|
22
|
-
// Feed UFC config directly to OpenFeature provider
|
|
23
22
|
if (action === 'apply' || action === 'modify') {
|
|
23
|
+
// Feed UFC config directly to OpenFeature provider
|
|
24
24
|
getOpenfeatureProxy()._setConfiguration(conf)
|
|
25
|
+
} else if (action === 'unapply') {
|
|
26
|
+
// Clear the configuration so evaluations return PROVIDER_NOT_READY,
|
|
27
|
+
// consistent with Go and Python which also set config to null on RC deletion.
|
|
28
|
+
// The evaluator returns PROVIDER_NOT_READY when config is null/undefined.
|
|
29
|
+
getOpenfeatureProxy()._setConfiguration(null)
|
|
25
30
|
}
|
|
26
31
|
})
|
|
27
32
|
}
|
|
@@ -4,7 +4,6 @@ const { trace, ROOT_CONTEXT, propagation } = require('@opentelemetry/api')
|
|
|
4
4
|
const { storage } = require('../../../datadog-core')
|
|
5
5
|
const { getAllBaggageItems, setBaggageItem, removeAllBaggageItems } = require('../baggage')
|
|
6
6
|
|
|
7
|
-
const tracer = require('../../')
|
|
8
7
|
const SpanContext = require('./span_context')
|
|
9
8
|
|
|
10
9
|
class ContextManager {
|
|
@@ -16,7 +15,7 @@ class ContextManager {
|
|
|
16
15
|
active () {
|
|
17
16
|
const store = this._store.getStore()
|
|
18
17
|
const baseContext = store || ROOT_CONTEXT
|
|
19
|
-
const activeSpan =
|
|
18
|
+
const activeSpan = storage('legacy').getStore()?.span
|
|
20
19
|
|
|
21
20
|
const storedSpan = store ? trace.getSpan(store) : null
|
|
22
21
|
|
|
@@ -60,7 +59,6 @@ class ContextManager {
|
|
|
60
59
|
// converts otel to dd
|
|
61
60
|
with (context, fn, thisArg, ...args) {
|
|
62
61
|
const span = trace.getSpan(context)
|
|
63
|
-
const ddScope = tracer.scope()
|
|
64
62
|
const run = () => {
|
|
65
63
|
const cb = thisArg == null ? fn : fn.bind(thisArg)
|
|
66
64
|
return this._store.run(context, cb, ...args)
|
|
@@ -74,7 +72,11 @@ class ContextManager {
|
|
|
74
72
|
for (const baggage of baggageItems) {
|
|
75
73
|
setBaggageItem(baggage[0], baggage[1].value)
|
|
76
74
|
}
|
|
77
|
-
if (span && span._ddSpan)
|
|
75
|
+
if (span && span._ddSpan) {
|
|
76
|
+
const ddSpan = span._ddSpan
|
|
77
|
+
const parentStore = storage('legacy').getStore(ddSpan._store) ?? storage('legacy').getStore()
|
|
78
|
+
return storage('legacy').run({ ...parentStore, span: ddSpan }, run)
|
|
79
|
+
}
|
|
78
80
|
return run()
|
|
79
81
|
}
|
|
80
82
|
|
|
@@ -61,7 +61,7 @@ function initializeOpenTelemetryLogs (config) {
|
|
|
61
61
|
// Create OTLP exporter using resolved config values
|
|
62
62
|
const exporter = new OtlpHttpLogExporter(
|
|
63
63
|
config.otelLogsUrl,
|
|
64
|
-
config.
|
|
64
|
+
config.OTEL_EXPORTER_OTLP_LOGS_HEADERS,
|
|
65
65
|
config.otelLogsTimeout,
|
|
66
66
|
config.otelLogsProtocol,
|
|
67
67
|
resourceAttributes
|
|
@@ -22,13 +22,14 @@ class OtlpHttpLogExporter extends OtlpHttpExporterBase {
|
|
|
22
22
|
* Creates a new OtlpHttpLogExporter instance.
|
|
23
23
|
*
|
|
24
24
|
* @param {string} url - OTLP endpoint URL
|
|
25
|
-
* @param {string} headers - Additional HTTP headers
|
|
25
|
+
* @param {Record<string, string>|undefined} headers - Additional HTTP headers parsed from the
|
|
26
|
+
* corresponding `OTEL_EXPORTER_OTLP_*_HEADERS` env by the MAP parser.
|
|
26
27
|
* @param {number} timeout - Request timeout in milliseconds
|
|
27
28
|
* @param {string} protocol - OTLP protocol (http/protobuf or http/json)
|
|
28
29
|
* @param {Resource} resource - Resource attributes
|
|
29
30
|
*/
|
|
30
31
|
constructor (url, headers, timeout, protocol, resource) {
|
|
31
|
-
super(url, headers, timeout, protocol, '
|
|
32
|
+
super(url, headers, timeout, protocol, 'logs')
|
|
32
33
|
this.transformer = new OtlpTransformer(resource, protocol)
|
|
33
34
|
}
|
|
34
35
|
|
|
@@ -58,7 +58,7 @@ function initializeOpenTelemetryMetrics (config) {
|
|
|
58
58
|
|
|
59
59
|
const exporter = new OtlpHttpMetricExporter(
|
|
60
60
|
config.otelMetricsUrl,
|
|
61
|
-
config.
|
|
61
|
+
config.OTEL_EXPORTER_OTLP_METRICS_HEADERS,
|
|
62
62
|
config.otelMetricsTimeout,
|
|
63
63
|
config.otelMetricsProtocol,
|
|
64
64
|
resourceAttributes
|
|
@@ -18,13 +18,14 @@ class OtlpHttpMetricExporter extends OtlpHttpExporterBase {
|
|
|
18
18
|
* Creates a new OtlpHttpMetricExporter instance.
|
|
19
19
|
*
|
|
20
20
|
* @param {string} url - OTLP endpoint URL
|
|
21
|
-
* @param {string} headers - Additional HTTP headers
|
|
21
|
+
* @param {Record<string, string>|undefined} headers - Additional HTTP headers parsed from the
|
|
22
|
+
* corresponding `OTEL_EXPORTER_OTLP_*_HEADERS` env by the MAP parser.
|
|
22
23
|
* @param {number} timeout - Request timeout in milliseconds
|
|
23
24
|
* @param {string} protocol - OTLP protocol (http/protobuf or http/json)
|
|
24
25
|
* @param {Resource} resource - Resource attributes
|
|
25
26
|
*/
|
|
26
27
|
constructor (url, headers, timeout, protocol, resource) {
|
|
27
|
-
super(url, headers, timeout, protocol, '
|
|
28
|
+
super(url, headers, timeout, protocol, 'metrics')
|
|
28
29
|
this.transformer = new OtlpTransformer(resource, protocol)
|
|
29
30
|
}
|
|
30
31
|
|
|
@@ -19,34 +19,31 @@ class OtlpHttpExporterBase {
|
|
|
19
19
|
/**
|
|
20
20
|
* Creates a new OtlpHttpExporterBase instance.
|
|
21
21
|
*
|
|
22
|
-
* @param {string} url - OTLP endpoint URL
|
|
23
|
-
* @param {string
|
|
22
|
+
* @param {string} url - OTLP endpoint URL (callers are expected to supply the full signal URL)
|
|
23
|
+
* @param {Record<string, string>|undefined} headers - Additional HTTP headers parsed from the
|
|
24
|
+
* corresponding `OTEL_EXPORTER_OTLP_*_HEADERS` env by the MAP parser.
|
|
24
25
|
* @param {number} timeout - Request timeout in milliseconds
|
|
25
26
|
* @param {string} protocol - OTLP protocol (http/protobuf or http/json)
|
|
26
|
-
* @param {string} defaultPath - Default path to use if URL has no path
|
|
27
27
|
* @param {string} signalType - Signal type for error messages (e.g., 'logs', 'metrics')
|
|
28
28
|
*/
|
|
29
|
-
constructor (url, headers, timeout, protocol,
|
|
30
|
-
const parsedUrl = new URL(url)
|
|
31
|
-
|
|
29
|
+
constructor (url, headers, timeout, protocol, signalType) {
|
|
32
30
|
this.protocol = protocol
|
|
33
31
|
this.signalType = signalType
|
|
34
32
|
|
|
35
|
-
// If no path is provided, use default path
|
|
36
|
-
const path = parsedUrl.pathname === '/' ? defaultPath : parsedUrl.pathname
|
|
37
33
|
const isJson = protocol === 'http/json'
|
|
38
34
|
|
|
35
|
+
// Initialize fields setUrl doesn't touch; it fills in hostname/port/path below.
|
|
39
36
|
this.options = {
|
|
40
|
-
hostname: parsedUrl.hostname,
|
|
41
|
-
port: parsedUrl.port,
|
|
42
|
-
path: path + parsedUrl.search,
|
|
43
37
|
method: 'POST',
|
|
44
38
|
timeout,
|
|
45
39
|
headers: {
|
|
46
40
|
'Content-Type': isJson ? 'application/json' : 'application/x-protobuf',
|
|
47
|
-
...
|
|
41
|
+
...headers,
|
|
48
42
|
},
|
|
49
43
|
}
|
|
44
|
+
|
|
45
|
+
this.setUrl(url)
|
|
46
|
+
|
|
50
47
|
this.telemetryTags = [
|
|
51
48
|
'protocol:http',
|
|
52
49
|
`encoding:${isJson ? 'json' : 'protobuf'}`,
|
|
@@ -61,6 +58,7 @@ class OtlpHttpExporterBase {
|
|
|
61
58
|
* @protected
|
|
62
59
|
*/
|
|
63
60
|
recordTelemetry (metricName, count, additionalTags) {
|
|
61
|
+
// @ts-expect-error - additionalTags is optional and can be undefined
|
|
64
62
|
if (additionalTags?.length > 0) {
|
|
65
63
|
tracerMetrics.count(metricName, [...this.telemetryTags, ...additionalTags || []]).inc(count)
|
|
66
64
|
} else {
|
|
@@ -91,6 +89,7 @@ class OtlpHttpExporterBase {
|
|
|
91
89
|
})
|
|
92
90
|
|
|
93
91
|
res.once('end', () => {
|
|
92
|
+
// @ts-expect-error - res.statusCode can be undefined
|
|
94
93
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
95
94
|
resultCallback({ code: 0 })
|
|
96
95
|
} else {
|
|
@@ -116,46 +115,15 @@ class OtlpHttpExporterBase {
|
|
|
116
115
|
}
|
|
117
116
|
|
|
118
117
|
/**
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* @
|
|
118
|
+
* Updates the target URL used by this exporter. The URL is used as-is per the OTel spec: the
|
|
119
|
+
* caller is responsible for including the signal-specific path (`/v1/traces` etc.).
|
|
120
|
+
* @param {string} url - New OTLP endpoint URL
|
|
122
121
|
*/
|
|
123
|
-
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
for (const char of headersString) {
|
|
130
|
-
if (readingKey) {
|
|
131
|
-
if (char === '=') {
|
|
132
|
-
readingKey = false
|
|
133
|
-
key = key.trim()
|
|
134
|
-
} else {
|
|
135
|
-
key += char
|
|
136
|
-
}
|
|
137
|
-
} else if (char === ',') {
|
|
138
|
-
value = value.trim()
|
|
139
|
-
if (key && value) {
|
|
140
|
-
headers[key] = value
|
|
141
|
-
}
|
|
142
|
-
key = ''
|
|
143
|
-
value = ''
|
|
144
|
-
readingKey = true
|
|
145
|
-
} else {
|
|
146
|
-
value += char
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// Add the last pair if present
|
|
151
|
-
if (!readingKey) {
|
|
152
|
-
value = value.trim()
|
|
153
|
-
if (value) {
|
|
154
|
-
headers[key] = value
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
return headers
|
|
122
|
+
setUrl (url) {
|
|
123
|
+
const parsedUrl = new URL(url)
|
|
124
|
+
this.options.hostname = parsedUrl.hostname
|
|
125
|
+
this.options.port = parsedUrl.port
|
|
126
|
+
this.options.path = parsedUrl.pathname + parsedUrl.search
|
|
159
127
|
}
|
|
160
128
|
|
|
161
129
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Protobuf Loader for OpenTelemetry Logs and Metrics
|
|
4
|
+
* Protobuf Loader for OpenTelemetry Logs, Traces, and Metrics
|
|
5
5
|
*
|
|
6
|
-
* This module loads protobuf definitions for OpenTelemetry logs and metrics.
|
|
6
|
+
* This module loads protobuf definitions for OpenTelemetry logs, traces, and metrics.
|
|
7
7
|
*
|
|
8
8
|
* VERSION SUPPORT:
|
|
9
9
|
* - OTLP Protocol: v1.7.0
|
|
@@ -20,6 +20,8 @@ const protobuf = require('../../../../../vendor/dist/protobufjs')
|
|
|
20
20
|
let _root = null
|
|
21
21
|
let protoLogsService = null
|
|
22
22
|
let protoSeverityNumber = null
|
|
23
|
+
let protoTraceService = null
|
|
24
|
+
let protoSpanKind = null
|
|
23
25
|
let protoMetricsService = null
|
|
24
26
|
let protoAggregationTemporality = null
|
|
25
27
|
|
|
@@ -28,6 +30,8 @@ function getProtobufTypes () {
|
|
|
28
30
|
return {
|
|
29
31
|
protoLogsService,
|
|
30
32
|
protoSeverityNumber,
|
|
33
|
+
protoTraceService,
|
|
34
|
+
protoSpanKind,
|
|
31
35
|
protoMetricsService,
|
|
32
36
|
protoAggregationTemporality,
|
|
33
37
|
}
|
|
@@ -39,6 +43,8 @@ function getProtobufTypes () {
|
|
|
39
43
|
'resource.proto',
|
|
40
44
|
'logs.proto',
|
|
41
45
|
'logs_service.proto',
|
|
46
|
+
'trace.proto',
|
|
47
|
+
'trace_service.proto',
|
|
42
48
|
'metrics.proto',
|
|
43
49
|
'metrics_service.proto',
|
|
44
50
|
].map(file => path.join(protoDir, file))
|
|
@@ -49,6 +55,10 @@ function getProtobufTypes () {
|
|
|
49
55
|
protoLogsService = _root.lookupType('opentelemetry.proto.collector.logs.v1.ExportLogsServiceRequest')
|
|
50
56
|
protoSeverityNumber = _root.lookupEnum('opentelemetry.proto.logs.v1.SeverityNumber')
|
|
51
57
|
|
|
58
|
+
// Get the message types for traces
|
|
59
|
+
protoTraceService = _root.lookupType('opentelemetry.proto.collector.trace.v1.ExportTraceServiceRequest')
|
|
60
|
+
protoSpanKind = _root.lookupEnum('opentelemetry.proto.trace.v1.SpanKind')
|
|
61
|
+
|
|
52
62
|
// Get the message types for metrics
|
|
53
63
|
protoMetricsService = _root.lookupType('opentelemetry.proto.collector.metrics.v1.ExportMetricsServiceRequest')
|
|
54
64
|
protoAggregationTemporality = _root.lookupEnum('opentelemetry.proto.metrics.v1.AggregationTemporality')
|
|
@@ -56,6 +66,8 @@ function getProtobufTypes () {
|
|
|
56
66
|
return {
|
|
57
67
|
protoLogsService,
|
|
58
68
|
protoSeverityNumber,
|
|
69
|
+
protoTraceService,
|
|
70
|
+
protoSpanKind,
|
|
59
71
|
protoMetricsService,
|
|
60
72
|
protoAggregationTemporality,
|
|
61
73
|
}
|