diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0d5eaf21ca5..ce8268ff016 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -183,6 +183,8 @@ /packages/dd-trace/test/tagger.spec.js @DataDog/apm-sdk-capabilities-js /packages/dd-trace/test/tracer.spec.js @DataDog/apm-sdk-capabilities-js +/scripts/generate-config-types.js @DataDog/apm-sdk-capabilities-js + # Feature Flagging /integration-tests/openfeature/ @DataDog/feature-flagging /packages/dd-trace/src/openfeature/ @DataDog/feature-flagging diff --git a/packages/dd-trace/src/config/config-base.d.ts b/packages/dd-trace/src/config/config-base.d.ts new file mode 100644 index 00000000000..7d9e05d09c8 --- /dev/null +++ b/packages/dd-trace/src/config/config-base.d.ts @@ -0,0 +1,7 @@ +import type { ConfigProperties } from './config-types' + +declare class ConfigBase {} + +interface ConfigBase extends ConfigProperties {} + +export = ConfigBase diff --git a/packages/dd-trace/src/config/config-base.js b/packages/dd-trace/src/config/config-base.js new file mode 100644 index 00000000000..3c21f87998f --- /dev/null +++ b/packages/dd-trace/src/config/config-base.js @@ -0,0 +1,5 @@ +'use strict' + +class ConfigBase {} + +module.exports = ConfigBase diff --git a/packages/dd-trace/src/config/config-types.d.ts b/packages/dd-trace/src/config/config-types.d.ts new file mode 100644 index 00000000000..6a83baf4630 --- /dev/null +++ b/packages/dd-trace/src/config/config-types.d.ts @@ -0,0 +1,78 @@ +import type { GeneratedConfig } from './generated-config-types' + +type PayloadTaggingRules = ReturnType | [] + +export interface ConfigProperties extends GeneratedConfig { + cloudPayloadTagging: GeneratedConfig['cloudPayloadTagging'] & { + requestsEnabled: boolean + responsesEnabled: boolean + rules: PayloadTaggingRules + } + commitSHA: string | undefined + debug: boolean + gcpPubSubPushSubscriptionEnabled: boolean + instrumentationSource: 'manual' | 'ssi' + isAzureFunction: boolean + isCiVisibility: boolean + isGCPFunction: boolean + isServiceNameInferred: boolean + isServiceUserProvided: boolean + logger: import('../../../../index').TracerOptions['logger'] | undefined + lookup: NonNullable + readonly parsedDdTags: Record + plugins: boolean + repositoryUrl: string | undefined + rules: import('../../../../index').SamplingRule[] + sampler: { + rateLimit: number + rules: import('../../../../index').SamplingRule[] + sampleRate: number | undefined + spanSamplingRules: import('../../../../index').SpanSamplingRule[] | undefined + } + stableConfig: { + fleetEntries: Record + localEntries: Record + warnings: string[] | undefined + } + tracePropagationStyle: GeneratedConfig['tracePropagationStyle'] +} + +type Primitive = bigint | boolean | null | number | string | symbol | undefined +type Terminal = Date | Function | Primitive | RegExp | URL + +type KnownStringKeys = Extract<{ + [K in keyof T]: + K extends string + ? string extends K + ? never + : K + : never +}[keyof T], string> + +type NestedConfigPath = [NonNullable] extends [Terminal] + ? never + : [NonNullable] extends [readonly unknown[]] + ? never + : [NonNullable] extends [object] + ? ConfigPathFor> + : never + +type ConfigPathFor = { + [K in KnownStringKeys]: + | K + | (NestedConfigPath extends never ? never : `${K}.${NestedConfigPath}`) +}[KnownStringKeys] + +type ConfigPathValueFor = + TPath extends `${infer TKey}.${infer TRest}` + ? TKey extends KnownStringKeys + ? ConfigPathValueFor, TRest> + : never + : TPath extends KnownStringKeys + ? T[TPath] + : never + +export type ConfigKey = KnownStringKeys +export type ConfigPath = ConfigPathFor +export type ConfigPathValue = ConfigPathValueFor +export type ConfigDefaults = Partial<{ [TPath in ConfigPath]: ConfigPathValue }> diff --git a/packages/dd-trace/src/config/generated-config-types.d.ts b/packages/dd-trace/src/config/generated-config-types.d.ts new file mode 100644 index 00000000000..71394bbd911 --- /dev/null +++ b/packages/dd-trace/src/config/generated-config-types.d.ts @@ -0,0 +1,582 @@ +// This file is generated from packages/dd-trace/src/config/supported-configurations.json +// by scripts/generate-config-types.js. Do not edit this file directly. + +export interface GeneratedConfig { + _DD_APM_TRACING_AGENTLESS_ENABLED: boolean; + apiKey: string | undefined; + apmTracingEnabled: boolean; + appKey: string | undefined; + appsec: { + apiSecurity: { + downstreamBodyAnalysisSampleRate: number; + enabled: boolean; + endpointCollectionEnabled: boolean; + endpointCollectionMessageLimit: number; + maxDownstreamRequestBodyAnalysis: number; + sampleDelay: number; + }; + blockedTemplateGraphql: string | undefined; + blockedTemplateHtml: string | undefined; + blockedTemplateJson: string | undefined; + enabled: boolean | undefined; + eventTracking: { + mode: string; + }; + extendedHeadersCollection: { + enabled: boolean; + maxHeaders: number; + redaction: boolean; + }; + obfuscatorKeyRegex: string; + obfuscatorValueRegex: string; + rasp: { + bodyCollection: boolean; + enabled: boolean; + }; + rateLimit: number; + rules: string | undefined; + sca: { + enabled: boolean | undefined; + }; + stackTrace: { + enabled: boolean; + maxDepth: number; + maxStackTraces: number; + }; + wafTimeout: number; + }; + baggageMaxBytes: number; + baggageMaxItems: number; + baggageTagKeys: string[]; + ciVisAgentlessLogSubmissionEnabled: boolean; + ciVisibilityTestSessionName: string | undefined; + clientIpEnabled: boolean; + clientIpHeader: string | undefined; + cloudPayloadTagging: { + maxDepth: number; + request: string[] | undefined; + response: string[] | undefined; + }; + codeOriginForSpans: { + enabled: boolean; + experimental: { + exit_spans: { + enabled: boolean; + }; + }; + }; + crashtracking: { + enabled: boolean; + }; + dbm: { + injectSqlBaseHash: boolean; + }; + dbmPropagationMode: string; + DD_ACTION_EXECUTION_ID: string | undefined; + DD_AGENTLESS_LOG_SUBMISSION_URL: string | undefined; + DD_APM_FLUSH_DEADLINE_MILLISECONDS: number; + DD_AZURE_RESOURCE_GROUP: string | undefined; + DD_CIVISIBILITY_AGENTLESS_ENABLED: boolean; + DD_CIVISIBILITY_AGENTLESS_URL: string | undefined; + DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER: boolean; + DD_CIVISIBILITY_DANGEROUSLY_FORCE_COVERAGE: boolean; + DD_CIVISIBILITY_DANGEROUSLY_FORCE_TEST_SKIPPING: boolean; + DD_CIVISIBILITY_ENABLED: boolean; + DD_CIVISIBILITY_GIT_UNSHALLOW_ENABLED: boolean; + DD_CIVISIBILITY_RUM_FLUSH_WAIT_MILLIS: number; + DD_CIVISIBILITY_TEST_COMMAND: string | undefined; + DD_CIVISIBILITY_TEST_MODULE_ID: string | undefined; + DD_CIVISIBILITY_TEST_SESSION_ID: string | undefined; + DD_CUSTOM_TRACE_ID: string | undefined; + DD_ENABLE_NX_SERVICE_NAME: boolean; + DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_DIR: string; + DD_EXPERIMENTAL_TEST_OPT_GIT_CACHE_ENABLED: boolean; + DD_EXPERIMENTAL_TEST_OPT_SETTINGS_CACHE: string; + DD_EXTERNAL_ENV: string | undefined; + DD_GIT_BRANCH: string | undefined; + DD_GIT_COMMIT_AUTHOR_DATE: string | undefined; + DD_GIT_COMMIT_AUTHOR_EMAIL: string | undefined; + DD_GIT_COMMIT_AUTHOR_NAME: string | undefined; + DD_GIT_COMMIT_COMMITTER_DATE: string | undefined; + DD_GIT_COMMIT_COMMITTER_EMAIL: string | undefined; + DD_GIT_COMMIT_COMMITTER_NAME: string | undefined; + DD_GIT_COMMIT_HEAD_SHA: string | undefined; + DD_GIT_COMMIT_MESSAGE: string | undefined; + DD_GIT_COMMIT_SHA: string | undefined; + DD_GIT_FOLDER_PATH: string | undefined; + DD_GIT_PROPERTIES_FILE: string | undefined; + DD_GIT_PULL_REQUEST_BASE_BRANCH: string | undefined; + DD_GIT_PULL_REQUEST_BASE_BRANCH_SHA: string | undefined; + DD_GIT_REPOSITORY_URL: string | undefined; + DD_GIT_TAG: string | undefined; + DD_INTERNAL_PROFILING_TIMELINE_SAMPLING_ENABLED: boolean; + DD_LAMBDA_HANDLER: string | undefined; + DD_MINI_AGENT_PATH: string | undefined; + DD_PIPELINE_EXECUTION_ID: string | undefined; + DD_PLAYWRIGHT_WORKER: string | undefined; + DD_PROFILING_ASYNC_CONTEXT_FRAME_ENABLED: boolean; + DD_PROFILING_CODEHOTSPOTS_ENABLED: boolean; + DD_PROFILING_CPU_ENABLED: boolean; + DD_PROFILING_DEBUG_SOURCE_MAPS: boolean; + DD_PROFILING_DEBUG_UPLOAD_COMPRESSION: string; + DD_PROFILING_ENDPOINT_COLLECTION_ENABLED: boolean; + DD_PROFILING_EXPERIMENTAL_CODEHOTSPOTS_ENABLED: boolean; + DD_PROFILING_EXPERIMENTAL_CPU_ENABLED: boolean; + DD_PROFILING_EXPERIMENTAL_ENDPOINT_COLLECTION_ENABLED: boolean; + DD_PROFILING_EXPERIMENTAL_OOM_EXPORT_STRATEGIES: string[]; + DD_PROFILING_EXPERIMENTAL_OOM_HEAP_LIMIT_EXTENSION_SIZE: number; + DD_PROFILING_EXPERIMENTAL_OOM_MAX_HEAP_EXTENSION_COUNT: number; + DD_PROFILING_EXPERIMENTAL_OOM_MONITORING_ENABLED: boolean; + DD_PROFILING_EXPERIMENTAL_TIMELINE_ENABLED: boolean; + DD_PROFILING_EXPORTERS: string[]; + DD_PROFILING_HEAP_ENABLED: boolean | undefined; + DD_PROFILING_HEAP_SAMPLING_INTERVAL: number; + DD_PROFILING_PPROF_PREFIX: string; + DD_PROFILING_PROFILERS: string[]; + DD_PROFILING_SOURCE_MAP: boolean; + DD_PROFILING_TIMELINE_ENABLED: boolean; + DD_PROFILING_UPLOAD_PERIOD: number; + DD_PROFILING_UPLOAD_TIMEOUT: number; + DD_PROFILING_V8_PROFILER_BUG_WORKAROUND: boolean; + DD_PROFILING_WALLTIME_ENABLED: boolean | undefined; + DD_ROOT_JS_SESSION_ID: string | undefined; + DD_RUNTIME_METRICS_FLUSH_INTERVAL: number; + DD_SPAN_SAMPLING_RULES_FILE: string | undefined; + DD_TELEMETRY_FORWARDER_PATH: string | undefined; + DD_TEST_FLEET_CONFIG_PATH: string | undefined; + DD_TEST_LOCAL_CONFIG_PATH: string | undefined; + DD_TRACE_AEROSPIKE_ENABLED: boolean; + DD_TRACE_AI_ENABLED: boolean; + DD_TRACE_AMQP10_ENABLED: boolean; + DD_TRACE_AMQPLIB_ENABLED: boolean; + DD_TRACE_ANTHROPIC_ENABLED: boolean; + DD_TRACE_APOLLO_ENABLED: boolean; + DD_TRACE_APOLLO_GATEWAY_ENABLED: boolean; + DD_TRACE_APOLLO_SERVER_CORE_ENABLED: boolean; + DD_TRACE_APOLLO_SERVER_ENABLED: boolean; + DD_TRACE_APOLLO_SERVER_EXPRESS_ENABLED: boolean; + DD_TRACE_APOLLO_SERVER_FASTIFY_ENABLED: boolean; + DD_TRACE_APOLLO_SUBGRAPH_ENABLED: boolean; + DD_TRACE_AVSC_ENABLED: boolean; + DD_TRACE_AWS_SDK_AWS_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_AWS_ENABLED: boolean; + DD_TRACE_AWS_SDK_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_BEDROCKRUNTIME_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_BEDROCKRUNTIME_ENABLED: boolean; + DD_TRACE_AWS_SDK_CLOUDWATCHLOGS_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_CLOUDWATCHLOGS_ENABLED: boolean; + DD_TRACE_AWS_SDK_DYNAMODB_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_DYNAMODB_ENABLED: boolean; + DD_TRACE_AWS_SDK_ENABLED: boolean; + DD_TRACE_AWS_SDK_EVENTBRIDGE_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_EVENTBRIDGE_ENABLED: boolean; + DD_TRACE_AWS_SDK_KINESIS_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_KINESIS_ENABLED: boolean; + DD_TRACE_AWS_SDK_LAMBDA_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_LAMBDA_ENABLED: boolean; + DD_TRACE_AWS_SDK_NODE_HTTP_HANDLER_ENABLED: boolean; + DD_TRACE_AWS_SDK_REDSHIFT_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_REDSHIFT_ENABLED: boolean; + DD_TRACE_AWS_SDK_S3_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_S3_ENABLED: boolean; + DD_TRACE_AWS_SDK_SFN_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_SFN_CLIENT_ENABLED: boolean; + DD_TRACE_AWS_SDK_SFN_ENABLED: boolean; + DD_TRACE_AWS_SDK_SMITHY_CLIENT_ENABLED: boolean; + DD_TRACE_AWS_SDK_SNS_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_SNS_ENABLED: boolean; + DD_TRACE_AWS_SDK_SQS_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_SQS_ENABLED: boolean; + DD_TRACE_AWS_SDK_STATES_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_STATES_ENABLED: boolean; + DD_TRACE_AWS_SDK_STEPFUNCTIONS_BATCH_PROPAGATION_ENABLED: boolean; + DD_TRACE_AWS_SDK_STEPFUNCTIONS_ENABLED: boolean; + DD_TRACE_AXIOS_ENABLED: boolean; + DD_TRACE_AZURE_DURABLE_FUNCTIONS_ENABLED: boolean; + DD_TRACE_AZURE_EVENT_HUBS_ENABLED: boolean; + DD_TRACE_AZURE_EVENTHUBS_BATCH_LINKS_ENABLED: boolean; + DD_TRACE_AZURE_FUNCTIONS_ENABLED: boolean; + DD_TRACE_AZURE_SERVICE_BUS_ENABLED: boolean; + DD_TRACE_AZURE_SERVICEBUS_BATCH_LINKS_ENABLED: boolean; + DD_TRACE_BEAUTIFUL_LOGS: boolean; + DD_TRACE_BLUEBIRD_ENABLED: boolean; + DD_TRACE_BODY_PARSER_ENABLED: boolean; + DD_TRACE_BSON_ENABLED: boolean; + DD_TRACE_BULLMQ_ENABLED: boolean; + DD_TRACE_BUNYAN_ENABLED: boolean; + DD_TRACE_CASSANDRA_DRIVER_ENABLED: boolean; + DD_TRACE_CHILD_PROCESS_ENABLED: boolean; + DD_TRACE_COLLECTIONS_ENABLED: boolean; + DD_TRACE_COMMONPLUGIN_ENABLED: boolean; + DD_TRACE_CONFLUENTINC_KAFKA_JAVASCRIPT_ENABLED: boolean; + DD_TRACE_CONNECT_ENABLED: boolean; + DD_TRACE_COOKIE_ENABLED: boolean; + DD_TRACE_COOKIE_PARSER_ENABLED: boolean; + DD_TRACE_COUCHBASE_ENABLED: boolean; + DD_TRACE_CRYPTO_ENABLED: boolean; + DD_TRACE_CUCUMBER_CUCUMBER_ENABLED: boolean; + DD_TRACE_CUCUMBER_ENABLED: boolean; + DD_TRACE_CYPRESS_ENABLED: boolean; + DD_TRACE_DEBUG: boolean; + DD_TRACE_DISABLED_INSTRUMENTATIONS: string; + DD_TRACE_DISABLED_PLUGINS: string | undefined; + DD_TRACE_DNS_ENABLED: boolean; + DD_TRACE_ELASTIC_ELASTICSEARCH_ENABLED: boolean; + DD_TRACE_ELASTIC_TRANSPORT_ENABLED: boolean; + DD_TRACE_ELASTICSEARCH_ENABLED: boolean; + DD_TRACE_ENCODING_DEBUG: boolean; + DD_TRACE_EXPERIMENTAL_RUNTIME_ID_ENABLED: boolean; + DD_TRACE_EXPERIMENTAL_SPAN_COUNTS: boolean; + DD_TRACE_EXPERIMENTAL_STATE_TRACKING: boolean; + DD_TRACE_EXPRESS_ENABLED: boolean; + DD_TRACE_EXPRESS_MONGO_SANITIZE_ENABLED: boolean; + DD_TRACE_EXPRESS_SESSION_ENABLED: boolean; + DD_TRACE_FASTIFY_ENABLED: boolean; + DD_TRACE_FETCH_ENABLED: boolean; + DD_TRACE_FIND_MY_WAY_ENABLED: boolean; + DD_TRACE_FS_ENABLED: boolean; + DD_TRACE_GCP_PUBSUB_PUSH_ENABLED: boolean; + DD_TRACE_GENERIC_POOL_ENABLED: boolean; + DD_TRACE_GOOGLE_CLOUD_PUBSUB_ENABLED: boolean; + DD_TRACE_GOOGLE_CLOUD_VERTEXAI_ENABLED: boolean; + DD_TRACE_GOOGLE_GAX_ENABLED: boolean; + DD_TRACE_GOOGLE_GENAI_ENABLED: boolean; + DD_TRACE_GRAPHQL_ENABLED: boolean; + DD_TRACE_GRAPHQL_TAG_ENABLED: boolean; + DD_TRACE_GRAPHQL_TOOLS_ENABLED: boolean; + DD_TRACE_GRAPHQL_TOOLS_EXECUTOR_ENABLED: boolean; + DD_TRACE_GRAPHQL_YOGA_ENABLED: boolean; + DD_TRACE_GRPC_ENABLED: boolean; + DD_TRACE_GRPC_GRPC_JS_ENABLED: boolean; + DD_TRACE_GRPC_PROTO_LOADER_ENABLED: boolean; + DD_TRACE_HANDLEBARS_ENABLED: boolean; + DD_TRACE_HAPI_BOOM_ENABLED: boolean; + DD_TRACE_HAPI_ENABLED: boolean; + DD_TRACE_HAPI_HAPI_ENABLED: boolean; + DD_TRACE_HONO_ENABLED: boolean; + DD_TRACE_HTTP_ENABLED: boolean; + DD_TRACE_HTTP2_ENABLED: boolean; + DD_TRACE_HTTPS_ENABLED: boolean; + DD_TRACE_IOREDIS_ENABLED: boolean; + DD_TRACE_IOVALKEY_ENABLED: boolean; + DD_TRACE_JEST_CIRCUS_ENABLED: boolean; + DD_TRACE_JEST_CONFIG_ENABLED: boolean; + DD_TRACE_JEST_CORE_ENABLED: boolean; + DD_TRACE_JEST_ENABLED: boolean; + DD_TRACE_JEST_ENVIRONMENT_JSDOM_ENABLED: boolean; + DD_TRACE_JEST_ENVIRONMENT_NODE_ENABLED: boolean; + DD_TRACE_JEST_GLOBALS_ENABLED: boolean; + DD_TRACE_JEST_REPORTERS_ENABLED: boolean; + DD_TRACE_JEST_RUNTIME_ENABLED: boolean; + DD_TRACE_JEST_TEST_SEQUENCER_ENABLED: boolean; + DD_TRACE_JEST_TRANSFORM_ENABLED: boolean; + DD_TRACE_JEST_WORKER_ENABLED: boolean; + DD_TRACE_KAFKAJS_ENABLED: boolean; + DD_TRACE_KNEX_ENABLED: boolean; + DD_TRACE_KOA_ENABLED: boolean; + DD_TRACE_KOA_ROUTE_ENABLED: boolean; + DD_TRACE_KOA_ROUTER_ENABLED: boolean; + DD_TRACE_KOA_WEBSOCKET_ENABLED: boolean; + DD_TRACE_LANGCHAIN_ANTHROPIC_ENABLED: boolean; + DD_TRACE_LANGCHAIN_COHERE_ENABLED: boolean; + DD_TRACE_LANGCHAIN_CORE_ENABLED: boolean; + DD_TRACE_LANGCHAIN_ENABLED: boolean; + DD_TRACE_LANGCHAIN_GOOGLE_GENAI_ENABLED: boolean; + DD_TRACE_LANGCHAIN_OPENAI_ENABLED: boolean; + DD_TRACE_LANGGRAPH_ENABLED: boolean; + DD_TRACE_LDAPJS_ENABLED: boolean; + DD_TRACE_LDAPJS_PROMISE_ENABLED: boolean; + DD_TRACE_LIMITD_CLIENT_ENABLED: boolean; + DD_TRACE_LODASH_ENABLED: boolean; + DD_TRACE_LOOPBACK_ENABLED: boolean; + DD_TRACE_MARIADB_ENABLED: boolean; + DD_TRACE_MEMCACHED_ENABLED: boolean; + DD_TRACE_MICROGATEWAY_CORE_ENABLED: boolean; + DD_TRACE_MIDDIE_ENABLED: boolean; + DD_TRACE_MOCHA_EACH_ENABLED: boolean; + DD_TRACE_MOCHA_ENABLED: boolean; + DD_TRACE_MOLECULER_ENABLED: boolean; + DD_TRACE_MONGODB_CORE_ENABLED: boolean; + DD_TRACE_MONGODB_ENABLED: boolean; + DD_TRACE_MONGODB_HEARTBEAT_ENABLED: boolean; + DD_TRACE_MONGOOSE_ENABLED: boolean; + DD_TRACE_MQUERY_ENABLED: boolean; + DD_TRACE_MULTER_ENABLED: boolean; + DD_TRACE_MYSQL_ENABLED: boolean; + DD_TRACE_MYSQL2_ENABLED: boolean; + DD_TRACE_NET_ENABLED: boolean; + DD_TRACE_NEXT_ENABLED: boolean; + DD_TRACE_NODE_CHILD_PROCESS_ENABLED: boolean; + DD_TRACE_NODE_REDIS_CLIENT_ENABLED: boolean; + DD_TRACE_NODE_SERIALIZE_ENABLED: boolean; + DD_TRACE_NYC_ENABLED: boolean; + DD_TRACE_OPENAI_ENABLED: boolean; + DD_TRACE_OPENSEARCH_ENABLED: boolean; + DD_TRACE_OPENSEARCH_PROJECT_OPENSEARCH_ENABLED: boolean; + DD_TRACE_OPENTELEMETRY_SDK_TRACE_NODE_ENABLED: boolean; + DD_TRACE_ORACLEDB_ENABLED: boolean; + DD_TRACE_OTEL_ENABLED: boolean; + DD_TRACE_PASSPORT_ENABLED: boolean; + DD_TRACE_PASSPORT_HTTP_ENABLED: boolean; + DD_TRACE_PASSPORT_LOCAL_ENABLED: boolean; + DD_TRACE_PG_CURSOR_ENABLED: boolean; + DD_TRACE_PG_ENABLED: boolean; + DD_TRACE_PG_NATIVE_ENABLED: boolean; + DD_TRACE_PG_QUERY_STREAM_ENABLED: boolean; + DD_TRACE_PINO_ENABLED: boolean; + DD_TRACE_PINO_PRETTY_ENABLED: boolean; + DD_TRACE_PLAYWRIGHT_CORE_ENABLED: boolean; + DD_TRACE_PLAYWRIGHT_ENABLED: boolean; + DD_TRACE_PLAYWRIGHT_TEST_ENABLED: boolean; + DD_TRACE_PRISMA_ENABLED: boolean; + DD_TRACE_PROCESS_ENABLED: boolean; + DD_TRACE_PROMISE_ENABLED: boolean; + DD_TRACE_PROMISE_JS_ENABLED: boolean; + DD_TRACE_PROPAGATION_STYLE: string[]; + DD_TRACE_PROTOBUFJS_ENABLED: boolean; + DD_TRACE_PUG_ENABLED: boolean; + DD_TRACE_Q_ENABLED: boolean; + DD_TRACE_REACT_DOM_ENABLED: boolean; + DD_TRACE_REACT_ENABLED: boolean; + DD_TRACE_REDIS_CLIENT_ENABLED: boolean; + DD_TRACE_REDIS_ENABLED: boolean; + DD_TRACE_REQUEST_ENABLED: boolean; + DD_TRACE_RESTIFY_ENABLED: boolean; + DD_TRACE_RHEA_ENABLED: boolean; + DD_TRACE_ROUTER_ENABLED: boolean; + DD_TRACE_SELENIUM_ENABLED: boolean; + DD_TRACE_SELENIUM_WEBDRIVER_ENABLED: boolean; + DD_TRACE_SEQUELIZE_ENABLED: boolean; + DD_TRACE_SHAREDB_ENABLED: boolean; + DD_TRACE_SMITHY_SMITHY_CLIENT_ENABLED: boolean; + DD_TRACE_SQLITE3_ENABLED: boolean; + DD_TRACE_SUFFIXPLUGIN_ENABLED: boolean; + DD_TRACE_TAGS: Record | undefined; + DD_TRACE_TEDIOUS_ENABLED: boolean; + DD_TRACE_UNDICI_ENABLED: boolean; + DD_TRACE_URL_ENABLED: boolean; + DD_TRACE_VITEST_ENABLED: boolean; + DD_TRACE_VITEST_RUNNER_ENABLED: boolean; + DD_TRACE_VM_ENABLED: boolean; + DD_TRACE_WHEN_ENABLED: boolean; + DD_TRACE_WINSTON_ENABLED: boolean; + DD_TRACE_WORKERPOOL_ENABLED: boolean; + DD_TRACE_WS_ENABLED: boolean; + DD_VITEST_WORKER: string | undefined; + dogstatsd: { + hostname: string; + port: string | number; + }; + dsmEnabled: boolean; + dynamicInstrumentation: { + captureTimeoutMs: number; + enabled: boolean; + probeFile: string | undefined; + redactedIdentifiers: string[]; + redactionExcludedIdentifiers: string[]; + uploadIntervalSeconds: number; + }; + env: string | undefined; + experimental: { + aiguard: { + enabled: boolean; + endpoint: string | undefined; + maxContentSize: number; + maxMessagesLength: number; + timeout: number; + }; + appsec: { + standalone: { + enabled: boolean; + }; + }; + b3: boolean; + enableGetRumData: boolean; + exporter: string; + flaggingProvider: { + enabled: boolean; + initializationTimeoutMs: number; + }; + }; + flakyTestRetriesCount: number; + flushInterval: number; + flushMinSpans: number; + gitMetadataEnabled: boolean; + graphqlErrorExtensions: string[]; + grpc: { + client: { + error: { + statuses: number[]; + }; + }; + server: { + error: { + statuses: number[]; + }; + }; + }; + headerTags: string[]; + heapSnapshot: { + count: number; + destination: string; + interval: number; + }; + hostname: string; + iast: { + dbRowsToTaint: number; + deduplicationEnabled: boolean; + enabled: boolean; + maxConcurrentRequests: number; + maxContextOperations: number; + redactionEnabled: boolean; + redactionNamePattern: string; + redactionValuePattern: string; + requestSampling: number; + securityControlsConfiguration: string | undefined; + stackTrace: { + enabled: boolean; + }; + telemetryVerbosity: string; + }; + inferredProxyServicesEnabled: boolean; + injectForce: boolean; + injectionEnabled: string | undefined; + installSignature: { + id: string | undefined; + time: string | undefined; + type: string | undefined; + }; + instrumentation_config_id: string | undefined; + isEarlyFlakeDetectionEnabled: boolean; + isFlakyTestRetriesEnabled: boolean; + isGitUploadEnabled: boolean; + isImpactedTestsEnabled: boolean; + isIntelligentTestRunnerEnabled: boolean; + isKeepingCoverageConfiguration: boolean; + isManualApiEnabled: boolean; + isTestDynamicInstrumentationEnabled: boolean; + isTestManagementEnabled: boolean; + langchain: { + spanCharLimit: number; + spanPromptCompletionSampleRate: number; + }; + legacyBaggageEnabled: boolean; + llmobs: { + agentlessEnabled: boolean | undefined; + enabled: boolean; + mlApp: string | undefined; + }; + logInjection: boolean; + logLevel: "debug" | "info" | "warn" | "error"; + memcachedCommandEnabled: boolean; + middlewareTracingEnabled: boolean; + openai: { + spanCharLimit: number; + }; + openAiLogsEnabled: boolean; + OTEL_EXPORTER_OTLP_ENDPOINT: string | undefined; + OTEL_LOG_LEVEL: "debug" | "info" | "warn" | "error" | undefined; + OTEL_LOGS_EXPORTER: "none" | "otlp" | undefined; + OTEL_METRICS_EXPORTER: "none" | "otlp" | undefined; + OTEL_RESOURCE_ATTRIBUTES: Record; + OTEL_SDK_DISABLED: boolean; + OTEL_TRACES_EXPORTER: "none" | "otlp"; + OTEL_TRACES_SAMPLER: "always_on" | "always_off" | "traceidratio" | "parentbased_always_on" | "parentbased_always_off" | "parentbased_traceidratio"; + OTEL_TRACES_SAMPLER_ARG: number | undefined; + otelBatchTimeout: number; + otelHeaders: string | undefined; + otelLogsEnabled: boolean; + otelLogsHeaders: string | undefined; + otelLogsProtocol: string; + otelLogsTimeout: number; + otelLogsUrl: string | undefined; + otelMaxExportBatchSize: number; + otelMaxQueueSize: number; + otelMetricsEnabled: boolean; + otelMetricsExportInterval: number; + otelMetricsExportTimeout: number; + otelMetricsHeaders: string | undefined; + otelMetricsProtocol: string; + otelMetricsTemporalityPreference: "DELTA" | "CUMULATIVE" | "LOWMEMORY"; + otelMetricsTimeout: number; + otelMetricsUrl: string | undefined; + otelProtocol: string; + otelTimeout: number; + peerServiceMapping: Record; + port: string | number; + profiling: { + enabled: 'true' | 'false' | 'auto'; + longLivedThreshold: number; + }; + propagateProcessTags: { + enabled: boolean; + }; + protocolVersion: string; + queryStringObfuscation: string; + rateLimit: number; + remoteConfig: { + enabled: boolean; + pollInterval: number; + }; + reportHostname: boolean; + resourceRenamingEnabled: boolean; + runtimeMetrics: { + enabled: boolean; + eventLoop: boolean; + gc: boolean; + }; + runtimeMetricsRuntimeId: boolean; + sampleRate: number | undefined; + samplingRules: import('../../../../index').SamplingRule[]; + scope: string | undefined; + service: string | undefined; + serviceMapping: Record; + site: string; + spanAttributeSchema: "v0" | "v1"; + spanComputePeerService: boolean; + spanLeakDebug: number; + spanRemoveIntegrationFromService: boolean; + spanSamplingRules: import('../../../../index').SpanSamplingRule[] | undefined; + startupLogs: boolean; + stats: { + enabled: boolean; + }; + tags: Record; + tagsHeaderMaxLength: number; + telemetry: { + debug: boolean; + dependencyCollection: boolean; + enabled: boolean; + heartbeatInterval: number; + logCollection: boolean; + metrics: boolean; + }; + testManagementAttemptToFixRetries: number; + trace: { + aws: { + addSpanPointers: boolean; + }; + dynamoDb: { + tablePrimaryKeys: string | undefined; + }; + nativeSpanEvents: boolean; + }; + traceId128BitGenerationEnabled: boolean; + traceId128BitLoggingEnabled: boolean; + tracePropagationBehaviorExtract: "continue" | "restart" | "ignore"; + tracePropagationExtractFirst: boolean; + tracePropagationStyle: { + extract: string[]; + inject: string[]; + }; + traceWebsocketMessagesEnabled: boolean; + traceWebsocketMessagesInheritSampling: boolean; + traceWebsocketMessagesSeparateTraces: boolean; + tracing: boolean; + url: string | URL; + version: string | undefined; + vertexai: { + spanCharLimit: number; + spanPromptCompletionSampleRate: number; + }; +} diff --git a/packages/dd-trace/test/config/generated-config-types.spec.js b/packages/dd-trace/test/config/generated-config-types.spec.js new file mode 100644 index 00000000000..452595157f5 --- /dev/null +++ b/packages/dd-trace/test/config/generated-config-types.spec.js @@ -0,0 +1,21 @@ +'use strict' + +const assert = require('node:assert/strict') +const { readFileSync } = require('node:fs') + +const { describe, it } = require('mocha') + +const { + generateConfigTypes, + OUTPUT_PATH, +} = require('../../../../scripts/generate-config-types') + +// TODO: Re-enable when landing the actual change. +describe.skip('generated config types', () => { + it('should stay in sync with supported-configurations.json', () => { + assert.strictEqual( + readFileSync(OUTPUT_PATH, 'utf8').replaceAll('\r\n', '\n'), + generateConfigTypes() + ) + }) +}) diff --git a/scripts/generate-config-types.js b/scripts/generate-config-types.js new file mode 100644 index 00000000000..66aecd34a78 --- /dev/null +++ b/scripts/generate-config-types.js @@ -0,0 +1,217 @@ +'use strict' + +const { readFileSync, writeFileSync } = require('node:fs') +const path = require('node:path') + +const CHECK_FLAG = '--check' +const OUTPUT_PATH_IN_REPOSITORY = 'packages/dd-trace/src/config/generated-config-types.d.ts' +const SUPPORTED_CONFIGURATIONS_PATH = path.join( + __dirname, + '..', + 'packages/dd-trace/src/config/supported-configurations.json' +) +const OUTPUT_PATH = path.join( + __dirname, + '..', + 'packages/dd-trace/src/config/generated-config-types.d.ts' +) + +const BASE_TYPES = { + array: 'string[]', + boolean: 'boolean', + decimal: 'number', + int: 'number', + json: 'unknown', + map: 'Record', + string: 'string', +} + +const SIMPLE_ALLOWED_VALUE = /^[A-Za-z0-9 _./:-]+$/ +const PROPERTY_TYPE_OVERRIDES = { + 'dogstatsd.port': 'string | number', + port: 'string | number', + samplingRules: "import('../../../../index').SamplingRule[]", + spanSamplingRules: "import('../../../../index').SpanSamplingRule[]", + url: 'string | URL', +} +const TRANSFORM_TYPE_OVERRIDES = { + normalizeProfilingEnabled: "'true' | 'false' | 'auto'", + parseOtelTags: 'Record', + sampleRate: 'number', + setIntegerRangeSet: 'number[]', + splitJSONPathRules: 'string[]', +} + +function createTreeNode () { + return { + children: new Map(), + type: undefined, + } +} + +function getPropertyName (canonicalName, entry) { + const configurationNames = entry.internalPropertyName ? [entry.internalPropertyName] : entry.configurationNames + return configurationNames?.[0] ?? canonicalName +} + +function withUndefined (type, entry) { + return entry.default === null ? `${type} | undefined` : type +} + +function getAllowedType (entry) { + if (!entry.allowed) { + return + } + + const values = entry.allowed.split('|') + if (values.length === 0 || values.some(value => !SIMPLE_ALLOWED_VALUE.test(value))) { + return + } + + const normalizedValues = values.map(value => { + if (entry.transform === 'toLowerCase') { + return value.toLowerCase() + } + if (entry.transform === 'toUpperCase') { + return value.toUpperCase() + } + return value + }) + + return normalizedValues + .map(value => JSON.stringify(value)) + .join(' | ') +} + +function getTypeForEntry (propertyName, entry) { + const override = PROPERTY_TYPE_OVERRIDES[propertyName] ?? + TRANSFORM_TYPE_OVERRIDES[entry.transform] ?? + getAllowedType(entry) ?? + BASE_TYPES[entry.type] + + if (!override) { + throw new Error(`Unsupported configuration type for ${propertyName}: ${entry.type}`) + } + + return withUndefined(override, entry) +} + +function addProperty (root, propertyName, type) { + const parts = propertyName.split('.') + let node = root + + for (const part of parts) { + node.children.set(part, node.children.get(part) ?? createTreeNode()) + node = node.children.get(part) + } + + if (node.type && node.type !== type) { + throw new Error(`Conflicting generated types for ${propertyName}: ${node.type} !== ${type}`) + } + + node.type = type +} + +function renderPropertyName (name) { + return /^[$A-Z_a-z][$\w]*$/.test(name) ? name : JSON.stringify(name) +} + +function renderNode (node, indentLevel = 0) { + const indent = ' '.repeat(indentLevel) + + if (node.children.size === 0) { + return /** @type {string} */ (node.type) + } + + const objectBody = [...node.children.entries()] + .sort(([left], [right]) => left.localeCompare(right)) + .map(([key, child]) => { + return `${indent} ${renderPropertyName(key)}: ${renderNode(child, indentLevel + 1)};` + }) + .join('\n') + const objectType = `{\n${objectBody}\n${indent}}` + + if (!node.type) { + return objectType + } + + return `${node.type} | ${objectType}` +} + +function generateConfigTypes () { + const { supportedConfigurations } = JSON.parse(readFileSync(SUPPORTED_CONFIGURATIONS_PATH, 'utf8')) + const root = createTreeNode() + + for (const [canonicalName, entries] of Object.entries(supportedConfigurations)) { + if (entries.length !== 1) { + throw new Error( + `Multiple entries found for canonical name: ${canonicalName}. ` + + 'This is currently not supported and must be implemented, if needed.' + ) + } + + const [entry] = entries + const propertyName = getPropertyName(canonicalName, entry) + const type = getTypeForEntry(propertyName, entry) + + addProperty(root, propertyName, type) + } + + return ( + '// This file is generated from packages/dd-trace/src/config/supported-configurations.json\n' + + '// by scripts/generate-config-types.js. Do not edit this file directly.\n\n' + + 'export interface GeneratedConfig ' + + renderNode(root) + + '\n' + ) +} + +function normalizeLineEndings (value) { + return value.replaceAll('\r\n', '\n') +} + +function writeGeneratedConfigTypes () { + const output = generateConfigTypes() + writeFileSync(OUTPUT_PATH, output) + return output +} + +function checkGeneratedConfigTypes () { + const generated = generateConfigTypes() + + const current = normalizeLineEndings(readFileSync(OUTPUT_PATH, 'utf8')) + if (current === generated) { + return true + } + + // eslint-disable-next-line no-console + console.error(`❌ Generated config types are out of date. + +The checked-in generated file does not match the current source-of-truth inputs: +- packages/dd-trace/src/config/supported-configurations.json +- index.d.ts + +To regenerate it locally, run: + npm run generate:config:types + +Then commit the updated file: + ${OUTPUT_PATH_IN_REPOSITORY} +`) + return false +} + +if (require.main === module) { + if (process.argv.includes(CHECK_FLAG)) { + process.exitCode = checkGeneratedConfigTypes() ? 0 : 1 + } else { + writeGeneratedConfigTypes() + } +} + +module.exports = { + checkGeneratedConfigTypes, + generateConfigTypes, + OUTPUT_PATH, + SUPPORTED_CONFIGURATIONS_PATH, + writeGeneratedConfigTypes, +}